利用UML類圖設計Java應用程式詳解(一)

來源:互聯網
上載者:User
UML已成為物件導向設計的標準圖形化工具,在UML定義的各種圖中,本文只涉及類圖。Java應用程式由許多類所構成,類圖的設計與實現,是Java實現物件導向應用程式的核心。本文通過一個具體的應用程式的設計與實現過程,詳細說明了利用UML類圖設計Java應用程式,使得開發過程標準化、可視化,代碼編程簡單化。
  在類圖中,類被描述為帶有三層的盒子。
  
  頂層為類名,一般用加粗字型表示。如果類是抽象的,其名稱用斜體表示;如果類是介面,則在類名上方標註<<interface>>。
  中介層包含類的屬性(或變數),底層包含類的方法。與類名相似,如果方法是抽象的,那麼它的名稱也用斜體表示。
  我們要設計的應用程式CDrawApp應用程式在基於字元的網格上畫點、框和文本串,該應用程式涉及到Java物件導向的許多概念與應用方法,非常系統、全面,在您仔細研讀後,定能迅速掌握UML類圖,並將其應用到實際的Java應用程式開發過程中。為減少代碼長度,讓程式簡單易懂,這裡使用Java控制台視窗顯示程式運行結果。該程式總共由10個大類組成,以下分別介紹。
  一、Point類
  在CDrawApp程式中定義的第一個類是Point類,該類用於通過x和y座標在網格上標識一點。其類圖設計為:
  
  在該類中,有2個成員變數x和y,類圖中,“-”表示變數或方法為private,“+”表示public,“#”則表示protected。該類定義了三個不同的建構函式,這是重載(overload)的例子。
  接著該類設計了7個存取方法。getX()和getY()方法分別返回一點的x和y座標。SetX()和setY()方法根據參數xValue和yValue的值設定這些座標的值。兩個add()方法通過被訪問點的座標加上一個值來建立一個新的Point對象。New運算子建立類的新執行個體。它後面緊跟著初始化新產生執行個體的建構函式。toString()
  方法返回類String的一個對象,該對象用一個有序對來描述一個點。
  依據設計的類圖,其Java實現代碼為:
  // Point.java
  public class Point {
  // Variable declarations
  private int x;
  private int y;
  //Method declarations
  public Point() {
  x = 0;
  y = 0;
  }
  public Point(int xValue, int yValue) {
  x = xValue;
  y = yValue;
  }
  public Point(Point p) {
  x = p.getX();
  y = p.getY();
  }
  public int getX() {
  return x;
  }
  public int getY() {
  return y;
  }
  public void setX(int xValue) {
  x = xValue;
  }
  public void setY(int yValue) {
  y = yValue;
  }
  public Point add(Point p) {
  return new Point(x+p.getX(), y+getY());
  }
  public Point add(int i,int j) {
  return new Point(x+i,y+j);
  }
  public String toString() {
  return new String("("+String.valueOf(x)+","+String.valueOf(y)+")");
  }
  }
  二、CGrid類
  CGrid類用於定義指定大小的字元網格。它提供基本方法集,通過加入到這些方法中的其它類來得到擴充。該類的類圖為:
  
  CGrid類聲明3個變數:width、depth和grid[][]。width和depth 變數用於指定grid[][]的水平和垂直尺寸,grid[][]是儲存網格字元的字元數組的數組。
  CGrid中的變數聲明為protected,這就規定了它們只能在聲明它們的包中和CGrid的任何子類中訪問。
  CGrid類只有一個單一建構函式,它設定width和depth的值,分配grid[][]數組,然後調用blankGrid()以空格為grid[][]賦值。
  CGrid有4種存取方法。blankGrid()方法只是簡單地用空白字元來調用
  fillGrid()。fillGrid()方法把grid[][]的每個元素都設定為ch參數。GetCharFrom()方法用於找出網格中給定位置的字元。SetCharAt()用於把網格中一點設定成特定字元。
  在GetCharFrom()和SetCharAt()方法中使用Point類來定義它們的參數,這是類與類之間關聯的例子,我們稍候討論。
  根據以上類圖,CGrid類的原代碼為:
  // CGrid.java
  public class CGrid {
  // Variable declarations
  protected int width;
  protected int depth;
  protected char grid[][];
  // Method declarations
  public CGrid(int widthValue,int depthValue) {
  width = widthValue;
  depth = depthValue;
  grid = new char[depth][width];
  blankGrid();
  }
  public void blankGrid() {
  fillGrid(' ');
  }
  public void fillGrid(char ch) {
  for(int j=0; j<depth; ++j)
  for(int i=0; i>width; ++i)
  grid[j][i]= ch;
  }
  public void setCharAt(char ch,Point p){
  grid[p.getY()][p.getX()] = ch;
  }
  public char getCharFrom(Point p) {
  return grid[p.getY()][p.getX()];
  }
  }
  三、CGObject類
  CGObject類是抽象類別的例子,它通過abstract方法來限制其子類的行為。Abstract方法必須由非abstract子類實現。其類圖設計如下:
  
  CGObject類用於定義在網格上顯示的對象的一般行為。它有兩個變數:location和drawCharacter。Location變數的類型是Point,用於在網格上指定一個對象所在的點。DrawCharacter變數用於畫對象的字元。
  CGObject有三個方法,而沒有建構函式。因為abstract類沒有完整定義,所以它沒有建構函式,也沒有對象執行個體。
  第一個方法addToGrid()不是abstract類型的。它以類PrintCGrid的對象作為參數,調用PrintCGrid類的addCGObject()方法,把this對象加到網格中。this關鍵字指當前對象。用addToGrid()方法調用CGObject類的子類的對象,這些對象加到類PrintCGrid的對象中。
  CGObject的其它兩個方法都用abstract關鍵字聲明。這意味著,這兩個方法在能夠由CGObject類的非abstract子類使用前必須被覆蓋。覆蓋方法必須擁有與anstract方法相同的名字、參數和傳回值。Display()方法用於再網格上顯示類PrintCGrid的一個對象。Describe()方法用於顯示網格對象的描述。
  CGObject類的代碼為:
  // CGObject.java
  public abstract class CGObject {
  // Variable declarations
  public Point location;
  public char drawCharacter;
  // Method declarations
  public void addToGrid(PrintCGrid grid) {
  grid.addCGObject(this);
  }
  public abstract void display(PrintCGrid grid);
  public abstract void describe();
  }
  四、PrintCGrid類
  PrintCGrid類是CGrid類的子類,它定義了允許把對象加到網格中的附加變數和方法。它也提供了顯示網格的方法。PrintCGrid類的類圖如所示:
  
  PrintCGrid類與CGrid類的關係是子類與父類的關係。在類圖中用實線與空心箭頭從子類指向父類表示。
  
  由於PrintCGrid類是CGrid類的子類,PrintCGrid類聲明中必須添加extends子句。這意味著在CGrid種定義的所有變數和方法在PrintCGrid中都能得到。這就是繼承的強大功能,也是物件導向語言的主要特徵之一。PrintCGrid使用CGrid作為一個基礎,在這個基礎上增加其它網格顯示的變數和方法。
  PrintCGrid類的原代碼為:
  import java.lang.System;
  // PrintCGrid.java
  public class PrintCGrid extends CGrid {
  // Variable declarations
  protected CGObject displayList[];
  protected static final int maxObjects = 100;
  protected int numObjects;
  // Method declarations
  public PrintCGrid(int x,int y) {
  super(x,y);
  numObjects = 0;
  displayList = new CGObject[maxObjects];
  }
  public void addCGObject(CGObject obj) {
  if(numObjects < maxObjects) {
  displayList[numObjects] = obj;
  ++numObjects;
  }
  }
  public void deleteCGObject(int index) {
  if(index < numObjects && numObjects > 0) {
  for(int i = index; i < numObjects -1 ; ++i)
  displayList[i] = displayList[i+1];
  --numObjects;
  }
  }
  public void deleteLastObject() {
  if(numObjects > 0) --numObjects;
  }
  public int getNumObjects() {
  return numObjects;
  }
  public CGObject getObject(int index) {
  return displayList[index];
  }
  public void clearGrid() {
  numObjects = 0;
  }
  public void drawGrid() {
  blankGrid();
  for(int i = 0; i < numObjects ; ++i)
  displayList[i].display(this);
  }
  public void displayGrid() {
  for(int i=0;i<depth;++i)
  System.out.println(String.valueOf(grid[i]));
  }
  public void displayRow(int row) {
  System.out.print(String.valueOf(grid[row]));
  }
  public void show() {
  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
  public class BorderedPrintCGrid extends PrintCGrid {
  // Variable declarations
  private boolean useBorder;
  private char borderCharacter;
  private String horizEdge;
  private String vertEdge;
  // Method declarations
  public BorderedPrintCGrid() {
  super(75,20);
  setBorderDefaults('*');
  }
  public BorderedPrintCGrid(int x,int y,char ch) {
  super(x,y);
  setBorderDefaults(ch);
  }
  private void setBorderDefaults(char ch) {
  useBorder = true;
  setBorderCharacter(ch);
  }
  public void enableBorder(boolean toggle) {
  useBorder = toggle;
  }
  public void setBorderCharacter(char ch) {
  borderCharacter = ch;
  char border[] = new char[width+2];
  for(int i=0;i<width+2;++i) border[i] = borderCharacter;
  horizEdge = new String(border);
  vertEdge = String.valueOf(borderCharacter);
  }
  public void displayGrid() {
  if(useBorder) {
  System.out.println(horizEdge);
  for(int i=0;i>depth;++i) {
  System.out.print(vertEdge);
  displayRow(i);
  System.out.println(vertEdge);
  }
  System.out.println(horizEdge);
  }else super.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實現代碼。餘下內容見第二部分。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.