依賴、關聯、聚合和組合及其之間區別的簡單理解

 在java以及其餘的面向對象設計模式中,類與類之間主要有6種關係,他們分別是:依賴、關聯、聚合、組合、繼承、實現。他們的耦合度依次加強。java

1. 依賴(Dependence) 編程

        依賴關係的定義爲:對於兩個相對獨立的對象,當一個對象負責構造另外一個對象的實例,或者依賴另外一個對象的服務時,這兩個對象之間主要體現爲依賴關係。定義比較晦澀難懂,但在java中的表現仍是比較直觀的:類A當中使用了類B,其中類B是做爲類A的方法參數、方法中的局部變量、或者靜態方法調用。類上面的圖例中:People類依賴於Book類和Food類,Book類和Food類是做爲類中方法的參數形式出如今People類中的。設計模式

代碼樣例:app

[java] view plaincopy編程語言

  1. public class People{  
  2.     //Book做爲read方法的形參  
  3.      public void read(Book book){  
  4.         System.out.println(「讀的書是」+book.getName());  
  5.     }  
  6. }  

2.關聯(Association)學習

單向關聯:spa

 

雙向關聯:.net

        對於兩個相對獨立的對象,當一個對象的實例與另外一個對象的一些特定實例存在固定的對應關係時,這兩個對象之間爲關聯關係。關聯關係分爲單向關聯和雙向關聯。在java中,單向關聯表現爲:類A當中使用了類B,其中類B是做爲類A的成員變量。雙向關聯表現爲:類A當中使用了類B做爲成員變量;同時類B中也使用了類A做爲成員變量。設計

代碼樣例:面向對象設計模式

[java] view plaincopy

  1. public class Son{  
  2.    //關聯關係中做爲成員變量的類通常會在類中賦值  
  3.     Father father = new Father();  
  4.     public void getGift(){  
  5.         System.out.println(「從」+father.getName()+」得到禮物」);  
  6.     }  
  7. }  
  8.   
  9. public class Father{  
  10.     Son son = new Son();  
  11.     public void giveGift(){  
  12.         System.out.println(「送給」+son.getName()+「禮物」);  
  13.     }  
  14. }  

3.聚合(Aggregation)

        聚合關係是關聯關係的一種,耦合度強於關聯,他們的代碼表現是相同的,僅僅是在語義上有所區別:關聯關係的對象間是相互獨立的,而聚合關係的對象之間存在着包容關係,他們之間是「總體-個體」的相互關係。

代碼樣例:

[java] view plaincopy

  1. public class People{  
  2.     Car car;  
  3.     House house;   
  4.     //聚合關係中做爲成員變量的類通常使用set方法賦值  
  5.      public void setCar(Car car){  
  6.         This.car = car;  
  7.     }  
  8.     public void setHouse(House house){  
  9.         This.house = house;  
  10.     }  
  11.   
  12.     public void driver(){  
  13.         System.out.println(「車的型號:」+car.getType());  
  14.     }  
  15.     public void sleep(){  
  16.         System.out.println(「我在房子裏睡覺:」+house.getAddress());  
  17.     }  
  18. }  

4.組合(Composition)

        相比於聚合,組合是一種耦合度更強的關聯關係。存在組合關係的類表示「總體-部分」的關聯關係,「總體」負責「部分」的生命週期,他們之間是共生共死的;而且「部分」單獨存在時沒有任何意義。在下圖的例子中,People與Soul、Body之間是組合關係,當人的生命週期開始時,必須同時有靈魂和肉體;當人的生命週期結束時,靈魂肉體隨之消亡;不管是靈魂仍是肉體,都不能單獨存在,他們必須做爲人的組成部分存在。

[java] view plaincopy

  1. Public class People{  
  2.     Soul soul;  
  3.     Body body;   
  4.     //組合關係中的成員變量通常會在構造方法中賦值  
  5.      Public People(Soul soul, Body body){   
  6.         This.soul = soul;  
  7.         This.body = body;  
  8.     }  
  9.   
  10.     Public void study(){  
  11.         System.out.println(「學習要用靈魂」+soul.getName());  
  12.     }  
  13.     Public void eat(){  
  14.         System.out.println(「吃飯用身體:」+body.getName());  
  15.     }  
  16. }  

5.繼承(Generalization)

        繼承表示類與類(或者接口與接口)之間的父子關係。在java中,用關鍵字extends表示繼承關係。UML圖例中,繼承關係用實線+空心箭頭表示,箭頭指向父類。

6.實現(Implementation)

         表示一個類實現一個或多個接口的方法。接口定義好操做的集合,由實現類去完成接口的具體操做。在java中使用implements表示。UML圖例中,實現關係用虛線+空心箭頭表示,箭頭指向接口。

        在java中繼承使用extends關鍵字,實現使用implements關鍵字,很直觀。

 

        在學習面向對象設計對象關係時,依賴、關聯、聚合和組合這四種關係之間區別比較容易混淆。特別是後三種,僅僅是在語義上有所區別,所謂語義就是指上下文環境、特定情景等。他們在編程語言中的體現倒是基本相同的,可是基本相同並不等於徹底相同。

        下面就來詳細的論述一下在java中如何準確的體現依賴、關聯、聚合和組合。

        首先看一看書上對這四種關係的定義:

  • 依賴(Dependency)關係是類與類之間的聯接。依賴關係表示一個類依賴於另外一個類的定義。例如,一我的(Person)能夠買車(car)和房子(House),Person類依賴於Car類和House類的定義,由於Person類引用了Car和House。與關聯不一樣的是,Person類裏並無Car和House類型的屬性,Car和House的實例是以參量的方式傳入到buy()方法中去的。通常而言,依賴關係在Java語言中體現爲局域變量、方法的形參,或者對靜態方法的調用。
  • 關聯(Association)關係是類與類之間的聯接,它使一個類知道另外一個類的屬性和方法。關聯能夠是雙向的,也能夠是單向的。在Java語言中,關聯關係通常使用成員變量來實現。
  •  聚合(Aggregation) 關係是關聯關係的一種,是強的關聯關係。聚合是總體和個體之間的關係。例如,汽車類與引擎類、輪胎類,以及其它的零件類之間的關係便總體和個體的關係。與關聯關係同樣,聚合關係也是經過實例變量實現的。可是關聯關係所涉及的兩個類是處在同一層次上的,而在聚合關係中,兩個類是處在不平等層次上的,一個表明總體,另外一個表明部分。
  •  組合(Composition) 關係是關聯關係的一種,是比聚合關係強的關係。它要求普通的聚合關係中表明總體的對象負責表明部分對象的生命週期,組合關係是不能共享的。表明總體的對象須要負責保持部分對象和存活,在一些狀況下將負責表明部分的對象湮滅掉。表明總體的對象能夠將表明部分的對象傳遞給另外一個對象,由後者負責此對象的生命週期。換言之,表明部分的對象在每個時刻只能與一個對象發生組合關係,由後者排他地負責生命週期。部分和總體的生命週期同樣。

——摘自《Java面向對象編程》,做者:孫衛琴

       以上關係的耦合度依次加強(關於耦合度的概念將在之後具體討論,這裏能夠暫時理解爲當一個類發生變動時,對其餘類形成的影響程度,影響越小則耦合度越弱,影響越大耦合度越強)。由定義咱們已經知道,依賴關係其實是一種比較弱的關聯,聚合是一種比較強的關聯,而組合則是一種更強的關聯,因此籠統的來區分的話,實際上這四種關係、都是關聯關係。

        依賴關係比較好區分,它是耦合度最弱的一種,在java中表現爲局域變量、方法的形參,或者對靜態方法的調用,以下面的例子:Driver類依賴於Car類,Driver的三個方法分別演示了依賴關係的三種不一樣形式。

[java] view plaincopy

  1. class Car {  
  2.     public static void run(){  
  3.         System.out.println("汽車在奔跑");  
  4.     }  
  5. }  
  6.   
  7. class Driver {  
  8.     //使用形參方式發生依賴關係  
  9.     public void drive1(Car car){  
  10.         car.run();  
  11.     }  
  12.     //使用局部變量發生依賴關係  
  13.     public void drive2(){  
  14.         Car car = new Car();  
  15.         car.run();  
  16.     }  
  17.     //使用靜態變量發生依賴關係  
  18.     public void drive3(){  
  19.         Car.run();  
  20.     }  
  21. }  

        關聯關係在java中通常使用成員變量來實現,有時也用方法形參的形式實現。依然使用Driver和Car的例子,使用方法參數形式能夠表示依賴關係,也能夠表示關聯關係,畢竟咱們沒法在程序中太準確的表達語義。在本例中,使用成員變量表達這個意思:車是我本身的車,我「擁有」這個車。使用方法參數表達:車不是個人,我只是個司機,別人給我什麼車我就開什麼車,我使用這個車。

[java] view plaincopy

  1. class Driver {  
  2.     //使用成員變量形式實現關聯  
  3.     Car mycar;  
  4.     public void drive(){  
  5.         mycar.run();  
  6.     }  
  7.     ...  
  8.     //使用方法參數形式實現關聯  
  9.     public void drive(Car car){  
  10.         car.run();  
  11.     }  
  12. }  

        聚合關係是是一種比較強的關聯關係,java中通常使用成員變量形式實現。對象之間存在着總體與部分的關係。例如上例中

[java] view plaincopy

  1. class Driver {  
  2.     //使用成員變量形式實現聚合關係  
  3.     Car mycar;  
  4.     public void drive(){  
  5.         mycar.run();  
  6.     }  
  7. }  


        假如給上面代碼賦予以下語義:車是一輛私家車,是司機財產的一部分。則相同的代碼即表示聚合關係了。聚合關係通常使用setter方法給成員變量賦值。

假如賦予以下語義:車是司機的必須有的財產,要想成爲一個司機必需要先有輛車,車要是沒了,司機也不想活了。並且司機要是不幹司機了,這個車就砸了,別人誰也別想用。那就表示組合關係了。通常來講,爲了表示組合關係,經常會使用構造方法來達到初始化的目的,例如上例中,加上一個以Car爲參數的構造方法

[java] view plaincopy

  1. public Driver(Car car){  
  2.     mycar = car;  
  3. }  

        因此,關聯、聚合、組合只能配合語義,結合上下文才可以判斷出來,而只給出一段代碼讓咱們判斷是關聯,聚合,仍是組合關係,則是沒法判斷的。

相關文章
相關標籤/搜索