三、 依賴倒置原則(DIP)
依賴倒置(Dependence Inversion Principle)原則講的是:要依賴於抽象,不要依賴於具體。
簡單的說,依賴倒置原則要求用戶端依賴於抽象耦合。原則表述:
抽象不應當依賴於細節;細節應當依賴於抽象;
要針對介面編程,不針對實現編程。
反面例子:
缺點:耦合太緊密,Light發生變化將影響ToggleSwitch。
解決辦法一:
將Light作成Abstract,然後具體類繼承自Light。
優點:ToggleSwitch依賴於抽象類別Light,具有更高的穩定性,而BulbLight與TubeLight繼承自Light,可以根據 "開放-封閉"原則進行擴充。只要Light不發生變化,BulbLight與TubeLight的變化就不會波及ToggleSwitch。
缺點:如果用ToggleSwitch控制一台電視就很困難了。總不能讓TV繼承自Light吧。
解決方案二:
優點:更為通用、更為穩定。
結論:
使用傳統過程化程式設計所建立的依賴關係,策略依賴於細節,這是糟糕的,因為策略受到細節改變的影響。依賴倒置原則使細節和策略都依賴於抽象,抽象的穩定性決定了系統的穩定性。
四、 介面隔離原則(ISP)
介面隔離原則(Interface Segregation Principle)講的是:使用多個專門的介面比使用單一的總介面總要好。換而言之,從一個客戶類的角度來講:一個類對另外一個類的依賴性應當是建立在最小介面上的。
過於臃腫的介面是對介面的汙染。不應該強迫客戶依賴於它們不用的方法。
My object-oriented umbrella(摘自Design Patterns Explained)
Let me tell you about my great umbrella. It is large enough to get into! In fact, three or four other people can get in it with me. While we are in it, staying out of the rain, I can move it from one place to another. It has a stereo system to keep me entertained while I stay dry. Amazingly enough, it can also condition the air to make it warmer or colder. It is one cool umbrella.
My umbrella is convenient. It sits there waiting for me. It has wheels on it so that I do not have to carry it around. I don't even have to push it because it can propel itself. Sometimes, I will open the top of my umbrella to let in the sun. (Why I am using my umbrella when it is sunny outside is beyond me!)
In Seattle, there are hundreds of thousands of these umbrellas in all kinds of colors. Most people call them cars.
實現方法:
1、 使用委託分離介面
2、 使用多重繼承分離介面
五、 合成/彙總複用原則(CARP)
合成/彙總複用原則(Composite/Aggregate Reuse Principle或CARP)經常又叫做合成複用原則(Composite Reuse Principle或CRP),就是在一個新的對象裡面使用一些已有的對象,使之成為新對象的一部分;新對象通過向這些對象的委派達到複用已有功能的目 的。
簡而言之,要盡量使用合成/彙總,盡量不要使用繼承。
o Design to interfaces.
o Favor composition over inheritance.
o Find what varies and encapsulate it.
(摘自:Design Patterns Explained)
區分"Has-A"與"Is-A"
"Is-A"是嚴格的分類學意義上定義,意思是一個類是另一個類的"一種"。而"Has-A"則不同,它表示某一個角色具有某一項責任。
導致錯誤的使用繼承而不是合成/彙總的一個常見的原因是錯誤的把"Has-A"當作"Is-A"。
例如:
實際上,僱員、經理、學生描述的是一種角色,比如一個人是"經理"必然是"僱員",另外一個人可能是"學生僱員",在上面的設計中,一個人無法同時擁有多個角色,是"僱員"就不能再是"學生"了,這顯然是不合理的。
錯誤源於把"角色"的等級結構與"人"的等級結構混淆起來,誤把"Has-A"當作"Is-A"。解決辦法:
六、 迪米特法則(LoD)
迪米特法則(Law of Demeter或簡寫LoD)又叫最少知識原則(Least Knowledge Principle或簡寫為LKP),也就是說,一個對象應當對其它對象有儘可能少的瞭解。
其它表述:
只與你直接的朋友們通訊
不要跟"陌生人"說話
每一個軟體單位對其它的單位都只有最少的知識,而且局限於那些與本單位密切相關的軟體單位。
迪米特法則與設計模式
Facade模式、Mediator模式
使民無知
《老子》第三章曰:"是以聖人之治,虛其心,實其腹,弱其志,常使民無知無欲。"使被"統治"的對象"愚昧"化,處於"無知"的狀態,可以使"統治"的成本降低。
所謂"最少知識"原則,實際上便是老子的"使民無知"的統治之術。
不相往來
《老子》云:"小國寡民……鄰國相望,雞犬之聲相聞,民至老死,不相往來。"將被統治的對象隔離開來,使它們沒有直接的通訊,可以達到分化瓦解,繼而分而治之的效果。迪米特法則與老子的"小國寡民"的統治之術不謀而合。
參考文獻:
閻宏,《Java與模式》,電子工業出版社
[美]James W. Cooper,《C#設計模式》,電子工業出版社
[美]Alan Shalloway James R. Trott,《Design Patterns Explained》,中國電力出版社
[美]Robert C. Martin,《敏捷式軟體開發 (Agile Software Development)-原則、模式與實踐》,清華大學出版社
[美]Don Box, Chris Sells,《.NET本質論 第1卷:公用語言運行庫》,中國電力出版社
http://www.dofactory.com/Patterns/Patterns.aspx