天天看點

面向對象七大原則

1. 單一職責原則(Single Responsibility Principle)

每一個類應該專注于做一件事情。

2. 裡氏替換原則(Liskov Substitution Principle)

超類存在的地方,子類是可以替換的。

3. 依賴倒置原則(Dependence Inversion Principle)

實作盡量依賴抽象,不依賴具體實作。高層子產品不應該直接依賴于低層子產品,高層子產品和低層子產品應該同時依賴一個抽象層。

4. 接口隔離原則(Interface Segregation Principle)

應當為用戶端提供盡可能小的單獨的接口,而不是提供大的總的接口。

5. 迪米特法則(Law Of Demeter)

又叫最少知識原則,一個軟體實體應當盡可能少的與其他實體發生互相作用。

6. 開閉原則(Open Close Principle)

面向擴充開放,面向修改關閉。

7. 組合/聚合複用原則(Composite/Aggregate Reuse Principle CARP)

盡量使用合成/聚合達到複用,盡量少用繼承。原則: 一個類中有另一個類的對象。

細則

單一職責原則(Single Responsibility Principle)

因為:可以降低類的複雜度,一個類隻負責一項職責,其邏輯肯定要比負責多項職責簡單的多;提高類的可讀性,提高系統的可維護性;變更引起的風險降低,變更是必然的,如果單一職責原則遵守的好,當修改一個功能時,可以顯著降低對其他功能的影響。需要說明的一點是單一職責原則不隻是面向對象程式設計思想所特有的,隻要是子產品化的程式設計,都适用單一職責原則。

是以:從大局上看Android中的Paint和Canvas等類都遵守單一職責原則,Paint和Canvas各司其職。

裡氏替換原則(Liskov Substitution Principle)

因為:裡氏替換原則告訴我們,在軟體中将一個基類對象替換成它的子類對象,程式将不會産生任何錯誤和異常,反過來則不成立,如果一個軟體實體使用的是一個子類對象的話,那麼它不一定能夠使用基類對象。裡氏替換原則是實作開閉原則的重要方式之一,由于使用基類對象的地方都可以使用子類對象,是以在程式中盡量使用基類類型來對對象進行定義,而在運作時再确定其子類類型,用子類對象來替換父類對象。

是以:使用裡氏替換原則時需要注意,子類的所有方法必須在父類中聲明,或子類必須實作父類中聲明的所有方法。盡量把父類設計為抽象類或者接口,讓子類繼承父類或實作父接口,并實作在父類中聲明的方法,運作時,子類執行個體替換父類執行個體,我們可以很友善地擴充系統的功能,同時無須修改原有子類的代碼,增加新的功能可以通過增加一個新的子類來實作。

從大局看Java的多态就屬于這個原則。

依賴倒置原則(Dependence Inversion Principle)

因為:具體依賴抽象,上層依賴下層。假設B是較A低的子產品,但B需要使用到A的功能,這個時候,B不應當直接使用A中的具體類;而應當由B定義一抽象接口,并由A來實作這個抽象接口,B隻使用這個抽象接口;這樣就達到了依賴倒置的目的,B也解除了對A的依賴,反過來是A依賴于B定義的抽象接口。通過上層子產品難以避免依賴下層子產品,假如B也直接依賴A的實作,那麼就可能造成循環依賴。

是以:采用依賴倒置原則可以減少類間的耦合性,提高系統的穩定性,減少并行開發引起的風險,提高代碼的可讀性和可維護性。

接口隔離原則(Interface Segregation Principle)

因為:提供盡可能小的單獨接口,而不要提供大的總接口。暴露行為讓後面的實作類知道的越少越好。譬如類ProgramMonkey通過接口CodeInterface依賴類CodeC,類ProgramMaster通過接口CodeInterface依賴類CodeAndroid,如果接口CodeInterface對于類ProgramMonkey和類CodeC來說不是最小接口,則類CodeC和類CodeAndroid必須去實作他們不需要的方法。将臃腫的接口CodeInterface拆分為獨立的幾個接口,類ProgramMonkey和類ProgramMaster分别與他們需要的接口建立依賴關系。也就是采用接口隔離原則。

是以:建立單一接口,不要建立龐大的接口,盡量細化接口,接口中的方法盡量少。也就是要為各個類建立專用的接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用。依賴幾個專用的接口要比依賴一個綜合的接口更靈活。接口是設計時對外部設定的約定,通過分散定義多個接口,可以預防外來變更的擴散,提高系統的靈活性和可維護性。

從大局來說Java的接口可以實作多繼承就是接口隔離原則的基礎保障。

迪米特法則(Law Of Demeter)

因為:類與類之間的關系越密切,耦合度也就越來越大,隻有盡量降低類與類之間的耦合才符合設計模式;對于被依賴的類來說,無論邏輯多複雜都要盡量封裝在類的内部;每個對象都會與其他對象有耦合關系,我們稱出現成員變量、方法參數、方法傳回值中的類為直接的耦合依賴,而出現在局部變量中的類則不是直接耦合依賴,也就是說,不是直接耦合依賴的類最好不要作為局部變量的形式出現在類的内部。

是以:一個對象對另一個對象知道的越少越好,即一個軟體實體應當盡可能少的與其他實體發生互相作用,在一個類裡能少用多少其他類就少用多少,尤其是局部變量的依賴類,能省略盡量省略。同時如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的互相作用。如果其中一個類需要調用另一個類的某一方法的話,可以通過第三者轉發這個調用。

從大局來說Android App開發中的多Fragment與依賴的Activity間互動通信遵守了這一法則。

開閉原則(Open Close Principle)

因為:開放封閉原則主要展現在對擴充開放、對修改封閉,意味着有新的需求或變化時,可以對現有代碼進行擴充,以适應新的情況。軟體需求總是變化的,世界上沒有一個軟體的是不變的,是以對軟體設計人員來說,必須在不需要對原有系統進行修改的情況下,實作靈活的系統擴充。

是以:可以通過Template Method模式和Strategy模式進行重構,實作對修改封閉,對擴充開放的設計思路。 封裝變化,是實作開放封閉原則的重要手段,對于經常發生變化的狀态,一般将其封裝為一個抽象,拒絕濫用抽象,隻将經常變化的部分進行抽象。

組合/聚合複用原則(Composite/Aggregate Reuse Principle CARP)

因為:其實整個設計模式就是在講如何類與類之間的組合/聚合。在一個新的對象裡面通過關聯關系(包括組合關系和聚合關系)使用一些已有的對象,使之成為新對象的一部分,新對象通過委派調用已有對象的方法達到複用其已有功能的目的。也就是,要盡量使用類的合成複用,盡量不要使用繼承。

如果為了複用,便使用繼承的方式将兩個不相幹的類聯系在一起,違反裡氏代換原則,哪是生搬硬套,忽略了繼承了缺點。繼承複用破壞資料封裝性,将基類的實作細節全部暴露給了派生類,基類的内部細節常常對派生類是透明的,白箱複用;雖然簡單,但不安全,不能在程式的運作過程中随便改變;基類的實作發生了改變,派生類的實作也不得不改變;從基類繼承而來的派生類是靜态的,不可能在運作時間内發生改變,是以沒有足夠的靈活性。

是以:組合/聚合複用原則可以使系統更加靈活,類與類之間的耦合度降低,一個類的變化對其他類造成的影響相對較少,是以一般首選使用組合/聚合來實作複用;其次才考慮繼承,在使用繼承時,需要嚴格遵循裡氏代換原則,有效使用繼承會有助于對問題的了解,降低複雜度,而濫用繼承反而會增加系統建構和維護的難度以及系統的複雜度,是以需要慎重使用繼承複用。

繼續閱讀