面向對象設計模式中,類與類之間主要有6種關系,他們分別是:依賴、關聯、聚合、組合、繼承、實現。他們的耦合度依次增強。
1.依賴(Dependence)
描述:
可以簡單的理解,就是一個類A使用到了另一個類B,而這種使用關系是具有偶然性的、臨時性的、非常弱的,但是B類的變化會影響到A。表現在代碼層面,類A當中使用了類B,其中類B是作為類A的方法參數、方法中的局部變量、或者靜態方法調用。注意,要避免雙向依賴。一般來說,不應該存在雙向依賴。
1 //book.h 2 class Book 3 {} 4 5 //food.h 6 class Food 7 {} 8 9 //people.h 10 #include "book.h" 11 #include "food.h" 12 class People 13 { 14 void read(Book book); 15 void eat(Food food); 16 }
2.關聯(Association)
描述:
對於兩個相對獨立的對象,當一個對象的實例與另一個對象的一些特定實例存在固定的對應關系時,這兩個對象之間為關聯關系。關聯關系分為單向關聯、雙向關聯和自身關聯。單向關聯表現為:類A當中使用了類B,其中類B是作為類A的成員變量。雙向關聯表現為:類A當中使用了類B作為成員變量;同時類B中也使用了類A作為成員變量。關聯關系必須被映射為對象引用或指針。
雙向關聯:
1 class Son 2 { 3 public: 4 void GetGift() 5 { 6 cout<<"從"<<father.GetName<<"取得禮物"; 7 } 8 9 private: 10 Father & father; 11 } 12 13 class Father 14 { 15 public: 16 void SetGift() 17 { 18 cout<<"送給"<<son.GetName<<"禮物"; 19 } 20 21 private: 22 Son & son; 23 }
3.聚合/組合
(1)聚合(Aggregation):C1聚合C2,但是C2可以離開C1而獨立存在(獨立存在的意思是在某個應用的問題域中這個類的存在有意義。這句話怎么解,請看下面組合里的解釋)。
1 class Car{} 2 class House{} 3 class People 4 { 5 public: 6 void Sleep(); 7 void Drive(); 8 private: 9 Car car; 10 House house; 11 }
(2)組合(Composition):C1組合C2,而且C2不能離開C1而獨立存在。但這是視問題域而定的,例如在關心汽車的領域里,輪胎是一定要組合在汽車類中的,因為它離開了汽車就沒有意義了。但是在賣輪胎的店鋪業務里,就算輪胎離開了汽車,它也是有意義的,這就可以用聚合了。在《敏捷開發》中還說到,A組合B,則A需要知道B的生存周期,即可能A負責生成或者釋放B,或者A通過某種途徑知道B的生成和釋放。
4.繼承(Generalization)
繼承表示類與類(或者接口與接口)之間的父子關系。
1 class Animal 2 { 3 virtual void Eat(); 4 virtual void Sleep(); 5 } 6 class People : public Animal 7 { 8 virtual void Eat(); 9 virtual void Sleep(); 10 void Study(); 11 }
5.實現(Implementation)
表示一個類實現一個或多個接口的方法。接口定義好操作的集合,由實現類去完成接口的具體操作。
注:這里再說一下重復度,其實看完了上面的描述之后,我們應該清楚了各個關系間的關系以及具體對應到代碼是怎么樣的,所謂的重復度,也只不過是上面的擴展,例如A和B有着“1對多”的重復度,那在A中就有一個列表,保存着B對象的N個引用,就是這樣而已。