Java面向對象16種原則
一 類的設計原則
1 依賴倒置原則-Dependency Inversion Principle (DIP)
2 裏氏替換原則-Liskov Substitution Principle (LSP)
3 接口分隔原則-Interface Segregation Principle (ISP)
4 單一職責原則-Single Responsibility Principle (SRP)
5 開閉原則-The Open-Closed Principle (OCP)
二 包的設計原則
6 重用發布等價原則-Release ReuseEquivalency Principle (REP)
7 無環依賴原則-The AcyclicDependencies Principle (ADP)
8 穩定依賴原則-The StableDependencies Principle (SDP)
9 穩定抽象等價原則-The StableAbstractions Principle (SAP)
10 共同封閉原則-The CommonClosure Principle (CCP)
11 全部重用原則-The Common Reuse Principle (CRP)
三 擴展原則
12 迪米特法則 -Least Knowledge Principle (LKP)
13 黑盒原則- BBP(Black Box Principle)
14 缺省抽象原則 -DAP(Default Abstraction Principle)
15 接口設計原則 -IDP(Interface Design Principle)
16 不要構造具體的超類原則 -DCSP(Don‘t Concrete SupperclassPrinciple)
1. Dependency Inversion Principle (DIP) - 依賴倒置原則
依賴:在程序設計中,如果一個模塊a使用或調用了另一個模塊b,我們稱模塊a依賴模塊b。
依賴倒置原則的2個重要方針:
為什麽叫做依賴倒置(Dependency Inversion)呢?
問題的提出:
Robert C. Martin在原文中給出了“Bad Design”的定義:
問題的解決:
為了解決上述問題,Robert C. Martin提出了OO設計的Dependency Inversion Principle (DIP) 原則。
2. Liskov Substitution Principle (LSP) - 裏氏替換原則
|
3. Interface Segregation Principle (ISP) - 接口分隔原則
ISP原則的違反例:
但這樣一來,依賴Door接口的CommonDoor卻不得不實現未使用的alarm()方法。違反了ISP原則。
遵循ISP原則的例:
Adapter設計模式的實現。 在Alarm接口定義alarm方法,在Door接口定義lock,unlock方法。接口之間無繼承關系。CommonDoor實現Door接口, 小結 Interface Segregation Principle (ISP)從對接口的使用上為我們對接口抽象的顆粒度建立了判斷基準:在為系統設計接口的時候,使用多個專門的接口代替單一的胖接口。 |
|
4. Single Responsibility Principle (SRP) - 單一職責原則
永遠不要讓一個類存在多個改變的理由。換句話說,如果一個類需要改變,改變它的理由永遠只有一個。如果存在多個改變它的理由,就需要重新設計該類。
職責的劃分 既然一個類不能有多個職責,那麽怎麽劃分職責呢? 讓ModemImplementation實現這兩個接口。我們註意到,ModemImplementation又組合了2個職責,這不是我們希望的,但有時這又是必須的。通常由於某些原因,迫使我們不得不綁定多個職責到一個類中,但我們至少可以通過接口的分割來分離應用程序關心的概念。 小結 Single Responsibility Principle (SRP)從職責(改變理由)的側面上為我們對類(接口)的抽象的顆粒度建立了判斷基準:在為系統設計類(接口)的時候應該保證它們的單一職責性。 |
5. The Open-Closed Principle (OCP) - 開閉原則
開閉原則(OCP:Open-Closed Principle)是指在進行面向對象設計(OOD:Object Oriented Design)中,設計類或其他程序單位時,應該遵循: 開閉原則的實現方法 為了滿足開閉原則的 對修改關閉(closed for modification) 原則以及擴展開放(open for extension) 原則,應該對軟件系統中的不變的部分加以抽象,在面向對象的設計中,
開閉原則的相對性 軟件系統的構建是一個需要不斷重構的過程,在這個過程中,模塊的功能抽象,模塊與模塊間的關系,都不會從一開始就非常清晰明了,所以構建100%滿足開閉原則的軟件系統是相當困難的,這就是開閉原則的相對性。但在設計過程中,通過對模塊功能的抽象(接口定義),模塊之間的關系的抽象(通過接口調用),抽象與實現的分離(面向接口的程序設計)等,可以盡量接近滿足開閉原則。
6. Release Reuse Equivalency Principle (REP) - 重用發布等價原則
|
7. The Acyclic Dependencies Principle (ADP) - 無環依賴原則
包之間的依賴結構必須是一個直接的無環圖形(DAG)。也就是說,在依賴結構中不允許出現環(循環依賴)。換成另一個說法是: 包間依賴不能是一個環狀形式。包間關系方面(耦合性)的原則
包的依賴
包的循環依賴 圖2:包的循環依賴 包的非循環依賴原則 包是一個比較合適的發布粒度,當修改了包中的代碼(類,模塊等)並發布新的版本時,我們需要把該包以及它所依賴的其它包一起發布。發布之後,還需要驗證系統是否能在新發布的版本下正常運作。
循環依賴的打破方法 如果包的依賴形成了環狀結構,怎麽樣打破這種循環依賴呢?
方法一:創建新的包
方法二:DIP與ISP設計原則
小結 無環依賴原則(ADP)為我們解決包之間的關系耦合問題。在設計包結構時,不能有循環依賴。
|
|
8. The Stable Dependencies Principle (SDP) - 穩定依賴原則
一個設計中的包之間的依賴應該朝著穩定的方向進行。一個包只應該依賴那些比自己更穩定的包。換成另一個說法是: 朝著穩定的方向進行依賴。包之間的關系方面(耦合性)的原則。
包的依賴 如果一個包A 中的類引用了包B中的類,我們稱包A依賴包B。 圖1(包A依賴包B)
包的穩定依賴原則 包應該依賴比自己更穩定的包。因為如果依賴一個不穩定的包,那麽當這個不穩定的包發生變化時,本身穩定的包也不得不發生變化,變得不穩定了。 圖1:穩定的包X
包的穩定性的判斷原則 可以通過下面的方法來判斷一個包的穩定系數:
穩定依賴原則(SDP)為我們解決包之間的關系耦合問題。在設計包結構時,包應該只依賴比自己更穩定的包。
|
9. The Stable AbstractionsPrinciple (SAP) - 穩定抽象等價原則
最穩定的包應該是最抽象的包。不穩定的包應該是具體的包。包的抽象程度跟它的穩定性成正比。穩定的包應該是抽象的包。 包的穩定抽象等價原則
穩定的包的構成
理想的體系結構應該是: 圖1:遵循穩定依賴原則(SDP)的理想的體系結構
小結 穩定抽象等價原則(SAP)為我們解決包之間的關系耦合問題。在設計包結構時,穩定的包應該是抽象的(由抽象類或接口構成),不穩定的包應該是具體的(由具體的實現類構成)。 |
10. The Common ClosurePrinciple (CCP) - 共同封閉原則
小結 共同封閉原則(CCP)從軟件功能的角度上為我們規範了包設計的一個原則:在設計包時,相互之間緊密關聯的類應該放在同一包裏。 |
11. The Common Reuse Principle (CRP) - 全部重用原則
包的所有類被一起重用。如果你重用了其中的一個類,就重用全部。換成另一個比較淺顯易懂的說法:沒有被一起重用的類不應該被組合在一起。CRP原則幫助我們決定哪些類應該被放到同一個包裏。包的內部關系方面(聚合性)的原則
全部重用原則(CRP)從用戶的角度上為我們規範了包設計的一個原則:在設計包時,相互之間沒有緊密關聯的類不應該放在同一包裏。
12. Least Knowledge Principle (LKP) -迪米特法則
迪米特法則(Law of Demeter,LoD)也稱為最少知識原則(Least Knowledge Principle,LKP)。 一個對象應該對其他對象有最少的了解。通俗地講,一個類應該對自己需要耦合或調用的類知道得最少,你(被耦合或調用的類)的內部是如何復雜都和我沒關系,那是你的事情,我就知道你提供的public方法,我就調用這麽多,其他的一概不關心。
含義:
朋友類的定義是這樣的:出現在成員變量、方法的輸入輸出參數中的類稱為成員朋友類,而出現在方法體內部的類不屬於朋友類。下面的代碼在方法體內部依賴了其他類,這嚴重違反迪米特法則
方法是類的一個行為,類竟然不知道自己的行為與其他類產生了依賴關系,這是不允許的。 正確的做法是:
註意:一個類只和朋友交流,不與陌生類交流,不要出現getA().getB().getC().getD()這種情況(在一種極端情況下允許出現這種訪問,即每一個點號後面的返回類型都相同),類與類之間的關系是建立在類間的,而不是方法間,因此一個方法盡量不引入一個類中不存在的對象,當然,JDK API提供的類除外。
一個類公開的public屬性或方法越多,修改時涉及的面也就越大,變更引起的風險擴散也就越大。因此,為了保持朋友類間的距離,在設計時需要反復衡量:是否還可以再減少public方法和屬性,是否可以修改為private、package-private(包類型,在類、方法、變量前不加訪問權限,則默認為包類型)、protected等訪問權限,是否可以加上final關鍵字等。 註意:迪米特法則要求類“羞澀”一點,盡量不要對外公布太多的public方法和非靜態的public變量,盡量內斂,多使用private、package-private、protected等訪問權限。
如果一個方法放在本類中,既不增加類間關系,也對本類不產生負面影響,就放置在本類中。
最後,迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以後,類的復用率才可以提高。
|
Principle –縱覽
----類原則 ----
1.單一職責原則 -Single Responsibility Principle(SRP)
就一個類而言,應該僅有一個引起它變化的原因。
(職責即為“變化的原因”。)
2.開放-封閉原則 - OpenClose Principle(OCP)
軟件實體(類、模塊、函數等)應該是可以擴展的,但是不可修改。
(對於擴展是開放的,對於更改是封閉的.
關鍵是抽象.將一個功能的通用部分和實現細節部分清晰的分離開來.
開發人員應該僅僅對程序中呈現出頻繁變化的那些部分作出抽象.
拒絕不成熟的抽象和抽象本身一樣重要. )
3.裏氏替換原則 -Liskov Substitution Principle(LSP)
子類型(subclass)必須能夠替換掉它們的基類型(superclass)。
4.依賴倒置原則(IoCP) 或 依賴註入原則 -Dependence Inversion Principle(DIP)
抽象不應該依賴於細節。細節應該依賴於抽象。
(Hollywood原則: "Don‘t call us, we‘ll call you".
程序中所有的依賴關系都應該終止於抽象類和接口。
針對接口而非實現編程。
任何變量都不應該持有一個指向具體類的指針或引用。
任何類都不應該從具體類派生。
任何方法都不應該覆寫他的任何基類中的已經實現了的方法。)
5.接口隔離原則(ISP)
不應該強迫客戶依賴於它們不用的方法。
接口屬於客戶,不屬於它所在的類層次結構。
(多個面向特定用戶的接口勝於一個通用接口。)
----包內聚原則 ----
6.重用發布等價原則(REP)
重用的粒度就是發布的粒度。
7.共同封閉原則(CCP)
包中的所有類對於同一類性質的變化應該是共同封閉的。
一個變化若對一個包產生影響,
則將對該包中的所有類產生影響,
而對於其他的包不造成任何影響。
8.共同重用原則(CRP)
一個包中的所有類應該是共同重用的。
如果重用了包中的一個類,
那麽就要重用包中的所有類。
(相互之間沒有緊密聯系的類不應該在同一個包中。)
----包耦合原則
9.無環依賴原則(ADP)
在包的依賴關系圖中不允許存在環。
10.穩定依賴原則(SDP)
朝著穩定的方向進行依賴。
應該把封裝系統高層設計的軟件(比如抽象類)放進穩定的包中,
不穩定的包中應該只包含那些很可能會改變的軟件(比如具體類)。
11.穩定抽象原則(SAP)
包的抽象程度應該和其穩定程度一致。
(一個穩定的包應該也是抽象的,一個不穩定的包應該是抽象的. )
----其它擴展原則----
12.BBP(Black Box Principle)黑盒原則
多用類的聚合,少用類的繼承。
13.DAP(Default Abstraction Principle)缺省抽象原則
在接口和實現接口的類之間引入一個抽象類,這個類實現了接口的大部分操作.
14.IDP(Interface Design Principle)接口設計原則
規劃一個接口而不是實現一個接口。
15.DCSP(Don‘t Concrete Supperclass Principle)不要構造具體的超類原則
避免維護具體的超類。
16.迪米特法則
一個類只依賴其觸手可得的類。
Java面向對象16種原則