UML中類圖的四種關係及其代碼實現

 在uml圖中 最複雜的也就是泛化,實現,依賴,關聯,這四種關係了,如果弄清了這幾種關係那麼在理解UML圖的時候就會變得輕車熟路了!

       如果你對着幾種關係一點都不熟悉的話可以看一下uml中的四種關係,這篇博客簡單的介紹了一下這幾種關係,本文將重點的介紹一下,這幾種關係在代碼裏如何實現的!

一、泛化關係


       我想這個也可能是最簡單的關係了,泛化就是特殊到一半的過程,也就是繼承的相反的過程,子類繼承自父類,而父類是從子類泛化而來!

        泛化(generalization)關係是一個類(稱爲子類、子接口)繼承另外的一個類(稱爲父類、父接口)的功能,並可以增加它自己的新功能的能力,繼承是類與類或者接口與接口之間最常見的關係;在Java中此類關係通過關鍵字extends明確標識,在c#中用:來表示。在設計時一般沒有爭議性。

<span style="font-size:18px;">namespace DEMO
{
    //類繼承類
    class ClassB: ClassA { }
    //接口繼承接口
    interface InterfaceB: InterfaceA { }
}</span>

二、實現關係

       實現(realization)關係指的是一個class類實現interface接口(可以是多個)的功能;實現是類與接口之間最常見的關係;在Java中此類關係通過關鍵字implements明確標識,在c#中用“:”表示在設計時一般沒有爭議性;

      

<span style="font-size:18px;">namespace DEMO
{
    //類實現接口
    class ClassC:InterfaceC{ }
}</span>


三、依賴關係  

  
       依賴(dependency)關係: 也是類與類之間的連接. 表示一個類依賴於另一個類的定義. 依賴關係總是單向的 。可以簡單的理解,就是一個類A使用到了另一個類B,而這種使用關係是具有偶然性的、、臨時性的、非常弱的,但是B類的變化會影響到A;比如某人要過河,需要借用一條船,此時人與船之間的關係就是依賴;表現在代碼層面,爲類B作爲參數被類A在某個method方法中使用。或者在方法體重聲明該類的變量,或者直接引用該類!

      

 

public class Boat {
    /// <summary>
    /// 過河
    /// </summary>
    public voidriverCrossing(){
        //啓動
        //過河
    }
    public staticvoid riverCrossingByShip(){
        //用大 船過河
    }
 
}//end Boat
 
public class Person {
    //通過參數的形式用Bote 類
    //Bote類被Person類的一個方法所持有,生命週期隨着方法執行結束而結束。
   /// <summary>
   /// 過河
   /// </summary>
   /// <paramname="bote">船的實例</param>
    public voidriverCrossing(Boat bote){
       bote.riverCrossing();
    }
    //在方法體重生命該類的變量
    //注意Bote類的生命週期,當riverCrossing方法被調用的時候,才被實例化。
    //持有Bote類的是Person類的一個方法,而不是Person類,這點是最重要的。
    public voidriverCrossing() {
        Boatbote = new Boat();
       bote.riverCrossing();
    }
    //直接應用該類
    public voidriverCrossing() {
        Boat.riverCrossingByShip();
    }
 
}//end Person


四、關聯關係


       關聯關係是實線加箭頭表示。表示類之間的關係比依賴要強。
       例如,水和氣候是關聯的,表示如下:

在代碼中的表現如下:

<span style="font-size:18px;">namespace DEMO
{
    /// <summary>
    /// 水
    /// </summary>
    class Water
    {
        //吧氣候類 的實例作爲該類的一個變量!
        public Climateclimate;
        publicWater() {
        }
    }
    /// <summary>
    /// 氣候
    /// </summary>
    class Climate
    {
        publicClimate()
        {
        }
    }
}</span>

可見,在Water類屬性中增加了Climate類。
關聯關係有單向關聯、雙向關聯、自身關聯、多維關聯等等。其中後三個可以不加箭頭。
單向關聯:

雙向關聯:

自身關聯:


多維關聯:


關聯和依賴的區別:
       從類的屬性是否增加的角度看:
       發生依賴關係的兩個類都不會增加屬性。其中的一個類作爲另一個類的方法的參數或者返回值,或者是某個方法的變量而已。
      發生關聯關係的兩個類,其中的一個類成爲另一個類的屬性,而屬性是一種更爲緊密的耦合,更爲長久的持有關係。
       從關係的生命週期來看:
       依賴關係是僅當類的方法被調用時而產生,伴隨着方法的結束而結束了。
關聯關係是當類實例化的時候即產生,當類銷燬的時候,關係結束。相比依賴講,關聯關係的生存期更長。
       關聯關係按關係強弱右分爲聚合 和組合 ,下邊用大雁和雁羣的例子講解一下!
大雁喜歡熱鬧害怕孤獨,所以它們一直過着羣居的生活,這樣就有了雁羣,每一隻大雁都有自己的雁羣,每個雁羣都有好多大雁,大雁與雁羣的這種關係就可以稱之爲聚合。
       另外每隻大雁都有兩隻翅膀,大雁與雁翅的關係就叫做組合。
由此可見:
聚合的關係明顯沒有組合緊密,大雁不會因爲它們的羣主將雁羣解散而無法生存;
而雁翅就無法脫離大雁而單獨生存——組合關係的類具有相同的生命週期。
聚合關係圖:


組合關係圖:


 在代碼中表現如下:

<span style="font-size:18px;">namespace DEMO
{
    /// <summary>
    /// 雁羣  
    /// </summary>
    class GooseGroup
    {
        public Goosegoose;
        publicGooseGroup(Goose goose) {
            this.goose= goose;
        }
    }
    /// <summary>
    /// 大雁
    /// </summary>
    class Goose
    {
        publicWing wing;
        publicGoose() {
           wing = new Wing();
        }
    }
}</span>


這兩種關係的區別是:
1.構造函數不同
        聚合類的構造函數中包含另一個類的實例作爲參數
        因爲構造函數中傳遞另一個類的實例,因此大雁類可以脫離雁羣類獨立存在。
        組合類的構造函數包含另一個類的實例化
        因爲在構造函數中進行實例化,因此兩者緊密耦合在一起,同生同滅,翅膀類不能脫離大雁類存在。
2.信息的封裝性不同
        在聚合關係中,客戶端可以同時瞭解GooseGroup類和Goose類,因爲他們是獨立的。
        在組合關係中,客戶端只認識大雁類,根本不知道翅膀類的存在,因爲翅膀類被嚴密地封裝在大雁類中。

總結:

        對於繼承、實現這兩種關係沒多少疑問,他們體現的是一種類與類、或者類與接口間的縱向關係;其他的四者關係則體現的是類與類、或者類與接口間的引用、橫向關係,是比較難區分的,有很多事物間的關係要想準備定位是很難的,前面也提到,這幾種關係都是語義級別的,所以從代碼層面並不能完全區分各種關係;但總的來說,後幾種關係所表現的強弱程度依次爲:組合>聚合>依賴。
————————————————
版權聲明:本文爲CSDN博主「張宏傑」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhanghongjie0302/article/details/39672859

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章