面向對象設計7大原則

轉自:https://www.cnblogs.com/sunflower627/p/4718702.html

 

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的實現,那麼就可能造成循環依賴。

所以:

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

從大局看Java的多態就屬於這個原則。

接口隔離原則(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)

因爲:

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

如果爲了複用,便使用繼承的方式將兩個不相干的類聯繫在一起,違反里氏代換原則,哪是生搬硬套,忽略了繼承了缺點。繼承複用破壞數據封裝性,將基類的實現細節全部暴露給了派生類,基類的內部細節常常對派生類是透明的,白箱複用;雖然簡單,但不安全,不能在程序的運行過程中隨便改變;基類的實現發生了改變,派生類的實現也不得不改變;從基類繼承而來的派生類是靜態的,不可能在運行時間內發生改變,因此沒有足夠的靈活性。

所以:

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

總結

至此,七大基本原則介紹完畢,很空洞,需要聯繫Java與android代碼去仔細體會琢磨。

發佈了86 篇原創文章 · 獲贊 25 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章