合成複用原則由成爲組合/聚合複用原則,儘量使用對象組合,而不是繼承來達到複用的目的
合成複用原則就是在一個新的對象裏通過關聯關係(包括組合關係和聚合關係)來使用一些已有的對象,使之成爲新對象的一部分;新對象通過委派調用已有對象的方法達到複用功能的目的。簡言之:複用時要儘量使用組合/聚合關係(關聯關係),少用繼承。
在面向對象設計中,可以通過兩種方法在不同的環境中複用已有的設計和實現,即通過組合、聚合關係或者通過繼承,但首先應該考慮組合/聚合,組合/聚合可以使系統更加靈活,降低類與類之間的耦合度,一個類的變化對其他類造成的影響相對較少;其次才考慮繼承,在使用繼承時,需要嚴格遵守里氏替換原則,有效使用繼承會有助於對問題的理解,降低複雜度,而濫用繼承反而會增加系統構建和維護的難度以及複雜度,因此需要慎重使用繼承複用。
通過繼承來進行復用的主要問題在於繼承複用會破壞系統的封裝性,以爲繼承會將基類的實現細節暴露給子類,由於基類的內部細節通常對子類來說是可見的,所以這種複用又稱“白箱”複用,如果基類發生改變,那麼子類的實現也不得不改變,從基類繼承而來的實現是靜態的,不可能在運行時發生改變,沒有足夠的靈活性,而且繼承只能在有限的環境中使用。
下面我們舉一個例子來對合成複用原則理解:
1 public class A 2 { 3 public void Method1() 4 { 5 Console.WriteLine("我是方法一"); 6 } 7 public void Method2() 8 { 9 Console.WriteLine("我是方法二"); 10 } 11 } 12 13 public class B : A 14 { 15 16 }
類A有2個方法,類B剛好需要調用這兩個方法,我們第一可能會想到直接繼承,這樣“多快好省“,但隨着業務進展,功能越來越複雜,A類需要增加其他方法,比如Method3 ,與B類毫無關聯,將會大大增加耦合性,合用複用原則的核心就是使用關聯,我們可以通過依賴、聚合、合成等關聯方法,降低耦合,提高可維護性和降低維護成本。
1 public class A 2 { 3 public void Method1() 4 { 5 Console.WriteLine("我是方法一"); 6 } 7 public void Method2() 8 { 9 Console.WriteLine("我是方法二"); 10 } 11 } 12 13 //依賴 14 public class B 15 { 16 public void Mthod1(A a) 17 { 18 Console.WriteLine("調用A方法"); 19 } 20 } 21 22 //聚合 23 public class C 24 { 25 private A a; 26 27 public void SetA(A al) 28 { 29 a = al; 30 } 31 } 32 33 //合成 34 public class D 35 { 36 public A a = new A(); 37 38 }