從類關係說起

溫故知新,最近更多的是研究和開發各種類庫,對設計的是有些感觸.以前在大學的時候,雖然知道,但是總歸是欠缺經驗的,現在,我嘗試用最通俗易懂的方式說出來.

所謂的設計不正是採用恰當的方式組織雷類關係麼?因此談設計我認爲首先要從類之間的關係開始說起.

在java開發中,有很多時候我們是在不斷的處理類與類之間關係,其中這六種關係是:依賴、關聯、聚合、組合、繼承、實現,他們的耦合度依次增強,其在UML的表示如下:
這裏寫圖片描述

下面我們分別對這幾種關係進行說明.

依賴

在實際生活中我們做任何一件事情幾乎都需要藉助其他物體的幫助,換句話說,我們依賴於其他的物體生活。比如:小明要開車,小明要吃飯,小明要生活等等,不難想象出依賴關係是現實世界中最普通的關係。對於以面向對象爲思想的語言世界來說,依賴也是最普遍和常見的關係。

在代碼層次上,依賴關係多表現爲函數的參數.

public class Person{
    public void drive(Car car){
        //
    }
}

UML表示:
這裏寫圖片描述


關聯

如果說依賴關係講求的臨時性,偶然性的話,那麼關聯關係則是一種持久性的關係。爲什麼這麼說呢?
小明吃飯藉助筷子,這種關係只存在小明吃飯的情況下,一旦小明不吃飯了,那麼這種依賴關係也就終止了。
與依賴關係不同,關聯對象的雙方地位同級,存在長期,固定的對應關係,即關聯是一種強依賴。關聯關係共分爲兩種:單向關聯和雙向關聯。所謂單向關聯通俗點講就是“你中有我,但我中未必有你”,比如小明擁有一輛車(注意和小明開車進行區分),但車這個對象可不擁有你啊。和單向關聯相對應的是雙向關聯,也即是”你中有我,我中有你”,比如夫妻就是一種雙向關聯.

在代碼層次上,關聯關係表現爲對象作爲另一個類的成員變量.

單向關聯

public class Person{
    private Car car;
    public void setCar(Car car){
        this.car=car;
    }
}

UML表示:
這裏寫圖片描述

雙向關聯

public class Husband{
    private Wife wife=new Wife();

    public void say(){
        System.out.println("my wife name:"+wife.getName());
    }

}

public class Wife{
    private Husband husband=new Husband();

    public void say(){
        System.out.println("my husband name:"+husband.getName());
    }

}

UML表示:
這裏寫圖片描述


聚合

聚合關係是一種強關聯關係,兩者之間最主呀的區別是在語意上:聚合之間的關係更像是”整體-部分”,有點組裝的含義,而關聯關係的對象間是相互獨立的,不存在組裝關係.
在現實世界中,分子是由原子組成的,汽車是由各種零部件組成的等,這都是聚合關係的最好說明.這裏要注意,組成A類型分子的原子也可以組成B類型的分子,這說明什麼呢?也就是部分可以單獨存在,換句話說就是整體和部分兩者的生命週期不是同步的.比如:水分子是由氧原子和氫原子組成的,你不能說沒有水分子就沒有氧原子和氫原子吧.

在代碼層次上,聚合和關聯兩者的形式一致,都表現爲成員變量.

public class Car{
    private Tyre tyre;
    private Engine engine;

    public void setTyre(Tyre tyre){
        this.tyre=tyre;
    }

    public void setEngine(Engine engine){
        this.engine=engine;
    }
}

UML表示:
這裏寫圖片描述

有些人寫成以下樣子:

public class Car{
    private Tyre tyre=new Tyre();
    private Engine engine=new Engine();


}

咋眼一看在代碼層次上符合啊,那這算不算是聚合關係呢?首先呢,我們肯定的說這是聚合關係.但僅僅是形勢上聚合的關係.爲什麼這麼說呢?

我們從真實世界中抽象汽車這個概念,進而將其轉化爲軟件世界中的Car,這也是java中提倡的面向對象編程的,但是呢,在從真實世界到軟件世界的這個過程中需要保證物體靜態屬性和動態屬性沒變.什麼意思呢,換言之就是,你將真實世界中的汽車轉成換成軟件世界中Car,反過來,也要保證從軟件世界中Car能夠轉換成真實世界中的汽車.如果不能保證轉換的一致性,那麼就說明,抽象過程中出現了問題.

現在將上邊的代碼中的Car轉成現實世界中的汽車,我們發現轉換後的汽車竟然不能換車輪了?這可能嗎?很顯然,在對抽象汽車到Car這個類的過程中出現了問題.那麼應該怎麼樣的呢?
除了一開始我們寫的那樣,還可以如下:

public class Car{
    private Tyre tyre=new Tyre();
    private Engine engine=new Engine();

    public void setTyre(Tyre tyre){
        this.tyre=tyre;
    }

    public void setEngine(Engine engine){
        this.engine=engine;
    }
}

組合

組合和聚合非常類似,都表示的”整體-部分”,但是組合要求整體和部分的生命週期是同步的,部分不能脫離整體而存在.不難發現,組合是一種強聚合關係.比如,人這個生命體由不同器官構成,其中我們拿心臟來說一下,人要活着必須依靠心臟,心臟不能脫離人這個生命體,兩者一旦分開,都會死亡.
在代碼層次上,通常表現爲類的成員變量,除此之外還要求這個成員變量在構造函數中創建.

public class People{
    private Heart heart;

    public People(){
        heart=new Heart();
    }
}

UML表示:
這裏寫圖片描述

到現在我們從微觀的角度瞭解依賴,關聯,聚合和組合這四種關係,從宏觀上來說,這四種關係體現的都是對象與對象之間的依賴,因此在某些方面,我們也同依賴來涵蓋這四種關係.在很多文章中,並沒有說到這一點,這也造成,很多情況下,大家對這幾個概念探地的時候感到很疑惑.

從真實世界中來看,對象與對象之間的關係其實可以分爲兩類,一是上邊宏觀所說的依賴,另一種則是我們下面要談的泛化


泛化

在開始解釋泛化之前,先來從extends說起:

extends的意思是延伸,擴展,繼承.從這個詞的角度來說,子類應該分爲兩層意思:

一種是增強原有類的功能,這體現的不是生物界的”父與子”關係.比如我現在擁有一個工具類Tools,現在我想要增強該工具類,按照開閉原則,我定義了UpdateTools extends Tools,此時你就不能說UpdateTools是Tools的”孩子”,因爲你發現這裏的UpdateTools僅僅是增強原有Tools類的功能,作爲功能擴展類來的.此時,我們稱其爲擴展比較合適.

另一種則就是體現生物界的”父與子”,即子類和父類在某些行爲或者屬性的表現不一樣.這時候,用單詞inherit來表示更合適,也就是我們常說的繼承的意思.

到現在,相信你已經明白了extends的含義.其實,實際中,我們使用繼承的目的就是爲了擴展,因此,可不做深究.
之所以談到這一點,是因爲去年帶過的一個實習生僅僅因爲不理解extends中的兩層,而覺得通過UpdateTools擴展Tools是有問題的.

下面我們在來說泛化.
泛化表示一個類(父類或接口)與其一個或者多個變體之間的關係.簡單的來說泛化表示類與類之間的擴展,接口與接口的擴展,類與接口之間的實現關係.
在java中用extends來表示擴展,用implements表示實現關係.

擴展:

public class Tools{
    public void print(){
        //do 
    }
}

public class UpdateTools extens Tools{
    public void printError(){
        //do
    |

}

繼承:

public class Father{
    public void getName(){
        //do
    }
}

public class Son{
    public void other(){
        //do
    }
}

UML表示:
這裏寫圖片描述

實現:

public interface UserService{
    void execute();
}

public class UserServiceImpl implements UserService{

    @override
    void execute(){
        //do
    }
}

UML表示:
這裏寫圖片描述

最後,我們來簡單的說說UML和Booch,OMT,OOSE的區別:
UML是在Booch,OMT,OOSE等面向對象的方法及其他許多方法和資料的基礎上發展起來的。UML方法集中了不同的圖形表示方法,剔除了其中容易引起混淆的,很少使用的符號,同時添加了一些新的符號。在1997年,UML成爲OMG的標準。到現在,你只需要瞭解UML的使用即可。

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