System.out.println(String.valueOf(grid[i]));
}
publicvoiddisplayRow(introw){
System.out.print(String.valueOf(grid[row]));
}
publicvoidshow(){
drawGrid();
displayGrid();
}
}
在以上代码中,PrintCGrid声明3个变量:
displayList[]、maxObjects和numObjects。
这些变量都声明为proceted,从而把对它们的访问限制在一个包中和PrintCGrid的子类中。
DisplayList[]变量是类CGObject(见以下类的介绍)的数组。
但这并不意味着该数组包含作为类CGObject实例的对象。
这是不可能的,因为CGObject是抽象的。
把DisplayList[]声明成类CGObject的数组的目的,是允许该数组包含CGObject类的子类的对象。
一般来说,如果一个变量声明成类X,那么可以把该变量赋值为X的子类的对象。
MaxObjects变量声明成static并且final。
使用static修饰符声明的变量,它们被作为一个类实例的所有对象公用,不会被每个实例复制,静态变量又成为类变量。
没有被声明成静态的变量是实例变量,对作为一个类的实例的每个对象进行复制。
Final修饰符用于把变量标识成常量。
用final修饰符声明的变量必须在声明时进行初始化,不能再声明之外的任何地方赋值。
MaxObjects常量初始化为100,表示可以加到displayList[]中的对象的最大数目。
NumObjects变量用于统计加到网格的displayList[]中的对象实际数目。
PrintCGrid有一个构造函数。
该构造函数有两个参数:
x和y,它们表示网格的水平和垂直方向的尺寸。
构造函数调用super()方法,并把这两个变量当着变元传递过去。
Super()方法是构造函数调用语句的一个例子。
它以x和y作为变元调用PrintCGrid的父类(即CGrid类)的构造函数。
CGrid的构造函数初始化其width和depth变量,分配grid[][]数组,并用空格给该数组元素赋值。
CGrid的构造函数运行完后,PrintCGrid的构造函数继续把numObjects设置为0,并分配displayList[]数组。
PrintCGrid提供10个访问方法。
AddCGObject()方法把对象加到displayList[]数组中。
DeleteCGObject()方法删除位于指定索引位置的对象。
所有的后续对象都向前移动,以填充被删除对象留下的空缺。
DeleteLastObject()方法通过简单地把numObjects减1来删除最后一个对象。
GetNumObjects方法返回displayList[]中的对象数目。
GetObject方法返回displayList[]中指定位置的对象。
clearGrid()方法通过把numObjects设置为0去清除所有对象。
DrawGrid()方法使用从CGrid类继承的方法清空网格,然后调用displayList[]中每个对象的display()方法。
displayGrid[]方法在控制台窗口中显示每一行网格。
它是继承的例子。
Grid[][]数祖在CGrid类中定义,由PrintCGrid所继承。
它由CGObject类的所有子类的drawGrid()方法和display()方法更新。
PrintGrid()类用它来在控制台窗口中打印字符。
ValueOf()方法用于displayGrid()方法中,它是String类的静态方法。
它把字符数组转换成String对象。
静态方法类似于静态变量,它整体上应用于类,而不是作为类实例的各个对象使用。
由于面向对象,静态方法只能访问静态变量。
所有静态方法都是定局的,不能被覆盖。
DisplayRow()方法在控制台窗口上显示一行网格,show()方法把drawGrid()和displayGrid()方法组合成一个方法。
五、BorderPrintCGrid类
BorderPrintCGrid类是PrintCGrid类的子类,它进一步扩展了CGrid类。
它增加了生成类PrintCGrid对象的边界的变量和方法。
类图见如下所示:
BorderPrintCGrid类有四个私有变量:
useBorder、borderCharacter、horizEdge和vertEdge。
UseBorder是boolean类型的变量,它决定边界是否应该显示。
BorderCharacter为用于显示边界的字符。
HorizEdge和vertEdge用于显示边界的水平和垂直边界的String对象。
BorderPrintCGrid类有两个。
第一个构造函数没有参数。
它调用PrintCGrid类的构造函数构造一个75字符宽20行高的网格,其边界字符为*。
SetBorderDefaults()方法用于初始化BorderedPrintCGrid类的变量。
第二个构造函数类似于第一个构造函数,但它提供了直接指定网格尺寸及边界字符的功能。
BorderPrintCGrid类提供4个访问方法。
SetBorderDefaults()方法使用enableBorder()方法和setBorderCharacter()方法初始化BorderedPrintCGrid类的变量。
enableBorder()方法把useBorder设置成true或false。
setBorderCharacter()方法设置displayGrid()方法所用的borderCharacter、horizEdge和vertEdge变量。
BorderedPrintCGrid类是PrintCGrid的子类,其类图关系表示为:
displayGrid()方法覆盖PrintCGrid类的displayGrid()方法。
通过重新定义该方法以满足自己的需要。
其中的super语句,将调用PrintCGrid.displayGrid()。
该类的实现代码为:
//BorderedPrintCGrid.java
publicclassBorderedPrintCGridextendsPrintCGrid{
//Variabledeclarations
privatebooleanuseBorder;
privatecharborderCharacter;
privateStringhorizEdge;
privateStringvertEdge;
//Methoddeclarations
publicBorderedPrintCGrid(){
super(75,20);
setBorderDefaults('*');
}
publicBorderedPrintCGrid(intx,inty,charch){
super(x,y);
setBorderDefaults(ch);
}
privatevoidsetBorderDefaults(charch){
useBorder=true;
setBorderCharacter(ch);
}
publicvoidenableBorder(booleantoggle){
useBorder=toggle;
}
publicvoidsetBorderCharacter(charch){
borderCharacter=ch;
charborder[]=newchar[width+2];
for(inti=0;ihorizEdge=newString(border);
vertEdge=String.valueOf(borderCharacter);
}
publicvoiddisplayGrid(){
if(useBorder){
System.out.println(horizEdge);
for(inti=0;i>depth;++i){
System.out.print(vertEdge);
displayRow(i);
System.out.println(vertEdge);
}
System.out.println(horizEdge);
}elsesuper.displayGrid();
}
}
到这里,我们的程序设计与实现已完成将近一半。
我们用UML类图分析了5个类,但这些类之间是如何相互作用而构成我们的应用程序呢?
现在我们回过头来分析前面5个类之间的相互关联。
首先我们分析继承概念在UML类图中的表示。
通过UML类图中的各类之间的继承关系表示法,我们清楚地知道,CGrid是超类,PrintCGrid是CGrid的子类,BorderedPrintCGrid是PrintCGrid以及CGrid的子类。
在Java类的代码实现中,一定要用相应的extends语句来表示实际的继承关系。
一般类与类之间的关系我们可以用关联来表达。
如在类CGrid中,在GetCharFrom()和SetCharAt()方法中我们使用了Point类来定义它们的参数,这是类CGrid对Point类的引用。
类CGrid可以引用多个Point对象,因此,在多重性的概念中,表示该类CGrid可以与多个Point对象关系。
在UML类图中,我们用一条实线表示这种关联为依赖关系,通过开叉的箭头表示是CGrid类引用Point类。
箭头上方的0..*表示可以与多个对象关联。
如果是0..1表示可以与1个对象关联;如果是1表示必须与1个对象关联;如果是1..*表示必须与至少1个对象关联。
同样,在PrintCGrid类中,在其变量申明中,有对CGObject的引用,并且也是多重引用。
其UML类图关系可以表示为:
因此,以上5个类之间的相互关系,用UML类图关系可以清楚地表示为:
本部分说明了5个类的UML类图表示、UML类图关系以及相应的Java实现代码。
利用UML类图设计Java应用程序详解
(二)
在第一部分中,我们实现了5个类。
在本部分中,我们接着说明如何利用UML类图来设计余下的各个类。
为减少篇幅,本部分着重讲解UML类图及应用,对Java实现代码不再详细描述。
六、CGPoint类
CGPoint类说明了如何利用非抽象类扩展抽象类。
CGPoint类是CGObject的子类,CGPoint类扩展了CGObject类,CGPoint类没有再它所继承的变量中增加变量,它所声明的方法只有构造函数和要求它实现的抽象方法。
其类图如下:
Java实现代码为:
//CGPoint.java
publicclassCGPointextendsCGObject{
//Methoddeclarations
publicCGPoint(intx,inty,charch){
location=newPoint(x,y);
drawCharacter=ch;
}
publicCGPoint(intx,inty){
this(x,y,'+');
}
publicCGPoint(Pointp){
this(p.getX(),p.getY(),'+');
}
p