熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

在UML中表示Java繼承和接口

2013-11-23 19:42:34  來源: Java高級技術 

  我們引入了UML類圖的概念比較了在Java編程語言和UML類圖中表示類屬性操作和關聯關系的不同之處下面我們來看看如何在UML中表示兩個重要的Java概念——繼承接口
  繼承
  在Java中我們可以聲明一個類擴展(extends)另一個類還可以聲明一個類實現(implements)一個或者多個接口下面我們來看看如何在UML中表達這些概念
  
  下面是三個Java類的基本骨架第一個類是代表某種支付方式的Payment抽象類另外兩個類分別擴展Payment類描述兩種不同的支付方式
  
  /** 描述支付方式的抽象類 */
  abstract public class Payment {
   public Payment() { }
  
   public Payment(BigDecimal amount) {
  thisamount = amount;
   }
  
   public BigDecimal getAmount() {
  return amount;
   }
  
   public void setAmount(BigDecimal amount) {
  thisamount = amount;
   }
  
   private BigDecimal amount;
  }
  
  /** 一個擴展了Payment類的子類描述信用卡支付方式 */
  public class CreditCardPayment extends Payment {
   public CreditCardPayment() {
   }
  
   public CreditCardPayment(BigDecimal amount) {
  super(amount);
   }
  
   public String getCardNumber() {
  return cardNumber;
   }
  
   public void setCardNumber(String cardNumber) {
  thiscardNumber = cardNumber;
   }
  
   public boolean authorize() {
  return false; //暫不實現
   }
  
   private String cardNumber;
  }
  
  /** 一個擴展了Payment類的子類描述現金支付方式 */
  public class CashPayment extends Payment {
   public CashPayment() {
  super();
   }
  
   public CashPayment(BigDecimal amount) {
  super(amount);
   }
  
   public BigDecimal getAmountTendered() {
  return amountTendered;
   }
  
   public void setAmountTendered(BigDecimal amountTendered) {
  thisamountTendered = amountTendered;
   }
  
   private BigDecimal amountTendered;
  
   public BigDecimal calcChange() {
  return amountTenderedsubtract(supergetAmount());
   }
  }
  圖一用UML顯示了同樣的三個類在操作和屬性聲明中類型和參數之類的細節都沒有顯示出來這是為了更清楚地顯示出類的整體結構以及各個類之間的關系
    
  圖一UML一般化關系
  Java中的extends關鍵詞聲明了繼承關系相當於UML中的一般化(Generalization也譯為泛化)關系在UML圖形中用子類向超類的實線空心封閉箭頭表示圖一額外增加了一個Sale類這是為了更清楚地說明UML一般化關系與UML定向關聯關系所用箭頭的不同關聯關系與一般化關系的另一個不同之處在於一般化關系的兩端不需要說明多重性或角色名稱
  顯然UML類圖比三個Java源代碼文件更清楚直觀地顯示出了三個類之間的繼承關系如果你要與別人探討設計思路繪制UML草圖也要比直接使用代碼簡單快捷得多
  
  也許有人會說系統的類結構圖就在他們的頭腦中他們只需要直接使用Java代碼實際上對於規模較大的系統這種說法顯然是不成立的即使對於規模較小的系統如果一定的時間之後要由其他程序員修改沒有UML圖也會寸步難行——很難保證每一個人都了解你頭腦中的類結構圖
  
  在UML中抽象類的標志是類的名字以斜體顯示在白板或紙張上手工畫UML草圖時很難區分字體是否是斜體為此一些人建議這些場合可以在類名稱的右下角加上{abstract}標記以示區別
  
  另一些人認為在白板上寫{abstrac t}顯得太羅嗦他們傾向於打破UML常規在類名稱的右下角加上一個表示零個實例如果在該位置寫上則表示該類是一個singleton類(永遠只有一個實例的類)如果在該位置寫上N則表示它是一個枚舉類(擁有固定實例數量的類如一星期中的天數彩虹的顏色等等)不過這一切都不是標准的UML只能用於手工繪制UML圖的場合看來也不可能得到UML建模工具的支持
  
  歷史知識UML首先由Rational公司的一個工作組發明Ration公司是UML建模工具Rose的生產者UML於年的OOPSLA會議上被公諸於世隨後OMG(對象管理組織)於年采用了UML規范不難理解繼續負責發展UML規范的OMG任務組包含了來自幾乎所有主流UML工具廠商的代表因此除了嚴格遵從規范的UML軟件工具在一些書籍或網頁上發現不規范的UML符號也不足為怪 
  繼承使得一個類能夠使用另一個類的屬性和方法就象使用自己的屬性和方法一樣當這類繼承機制第一次出現時人們普遍把它視為重用現有代碼的理想方法令人遺憾的是規模過於龐大的繼承樹變得很脆弱修改繼承樹的一部分就會在整棵繼承樹中引起一系列的連帶反映在面向對象的編程中如果要實現有效的封裝就應該讓改動局部化即一個地方的改動不至於引起其他地方的變化而修改繼承樹一個地方引起其他地方的變化恰恰違背了上述設計思想UML圖使得我們能夠方便地掌握繼承關系圖從而為應用繼承關系帶來了方便那麼什麼時候適合運用繼承關系呢?按照《Java Design》一書對於超類A和子類B執行如下檢查
  
  命題B是一個由A扮演的角色不成立
  
  B永遠不需要變形成為其他某些類別中的對象
  
  B擴展而不是覆蓋或廢棄A的行為
  
  A不僅僅是一個工具類(一些可以重用的實用功能)
  
  對於一個問題域(特定的業務對象環境)A和B定義了同一類型的對象或者是用戶事務角色實體(團體位置或其他東西)或其他物體的相似類別
  如果上述任意一個判斷不成立那麼把A和B定義成繼承關系可能是不合適的改用關聯關系可能更加穩固正確例如圖二違背上面的第一個判斷因為雇員是一個由人扮演的角色成立另外它還違背了第二個判斷因為雇員確實可能改變其類別(身份)例如某個時候它可能是顧客這樣一個既是顧客又是雇員的人就要有兩個獨立的對象來描述從而使保存在Person類裡面的信息重復出現帶來了兩個數據副本之間數據不一致的風險
    
  圖二不恰當的extends用法
  圖三顯示了改用關聯關系後的UML圖現在一個人可以在同一時刻(或不同時刻)既是顧客又是雇員(或任意一種)
    
  圖三改用關聯關系
  接口
  Java編程語言中接口(Interface)的概念也能夠與UML概念匹配UML中的接口是一種實現繼承的形式但這種繼承形式與Java中通過關鍵詞extends實現的繼承有所不同
  
  在Java中extends關鍵詞描述了一種繼承形式它既繼承接口也繼承行為這種類型的繼承有時被稱為Subclassing與其他的面象對象編程語言不同Java類只能從一個類繼承許多時候設計UML圖的人熟悉多種編程語言常常會引入多重繼承的思想例如C++的多重繼承思想從已有的Java代碼生成UML圖(這個過程稱為反向工程)不會帶來多重繼承的問題但如果要求一個Java程序員去實現一個帶有多重繼承的UML類圖就會出現問題如果多重繼承中的超類是純抽象類這部分類可以用Java的接口來描述但是如果只做這種轉換不足以把UML類圖中的多重繼承全部轉換成單重繼承這時就必須修改UML類圖重新建模了
  
  雖然Java不支持C++之類語言那樣的多重繼承但它支持實現多重接口這種由Java關鍵詞implements聲明的繼承只繼承接口這種繼承有時被稱作Subtyping在UML中實現接口的類與接口定義之間的關系叫做Realization關系用一個虛線封閉箭頭表示從實現接口的類指向接口接口本身的UML圖與普通類一樣但它的名字上面要加上<>圖四由圖一修改而成Payment類被一個接口取代(關於Realization名稱的說明Realization最常見的中文譯名是實現但是Java的implements也叫做實現為避免混淆本文中凡是出現Realization的地方一律直接使用英文)
    
  圖四接口與實現接口的類之間的Realization關系
  接口可以從一個或者多個其他接口擴展UML一般化關系(實線封閉箭頭)可用來描述這種關系如圖五所示
    
  圖五UML一般化關系用來表示一個接口擴展了一個或者多個其他接口
  UML還支持另一種接口符號即用圓圈表示接口(加上連線之後就成了棒棒糖的樣子)但這種表示法多用於UML組件圖在UML類圖中比較少見
  如果UML圖規模較大有大量的類實現一個常用接口整個UML圖可能亂成一團糟《Java Design》一書提出了一種簡化方法後來又被《Streamlined Object Modeling》一書的作者采用這就是在實現接口的類中用接口的名字替代從接口繼承的方法不過這不屬於標准方法遺憾的是目前似乎還沒有工具支持這種轉換圖六是用Together ControlCenter工具加工出來的簡化類圖
   From:http://tw.wingwit.com/Article/program/Java/gj/201311/27335.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.