天天看點

初識面向對象設計--七大原則概述面向對象設計有以下幾種原則

面向對象設計有以下幾種原則

1.開閉原則 Open-Close Principle(OCP)

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

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

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

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

6.迪米特原則/最少知識原則 Law of Demeter or Least Knowledge Principle(LOD orLKP)

7.組合/聚合複用原則 Composition/Aggregation Reuse Principle(CARP)

概述

1.開閉原則:

含義:對擴充開放,對修改關閉。

我們寫的代碼,不能因為需求變化了就要修改原有代碼,我們可以通過新增代碼的方式來解決變化的需求。在現實中,我們要盡量縮小這種修改。

意義:如果每次需求變動都要去修改既有代碼,那原有的代碼就存在修改錯誤的風險,當然這其中存在有意和無意的修改,都會導緻原有正常運作的功能失效的風險,這樣很有可能引起蝴蝶效應,使維護工作劇增。

潛台詞:控制需求變動風險,縮小維護成本。

其他的原則都是為此原則服務的。

2.裡氏替換原則:

含義:子類可以在任何地方替換它的父類。

這是多态的前提,我們後面許多所謂的靈活,都是不改變聲明類型的情況下,改變執行個體化類來完成的需求變更。

潛台詞:盡量使用精準的抽象類或者接口。

3.單一職責原則:

含義:類的職責單一,引起類變化的原因單一。

靈活的前提,将類拆分成最小的職能機關,那組合與複用就簡單的多,如果一個類做的事情太多,在組合的時候,就會産生不必要的方法,這是一種污染。

潛台詞:拆分到最小機關,解決複用群組合問題。

4.接口隔離原則:

含義:盡量使用職能單一的接口,而不使用職能複雜、全面的接口。

它是單一職責的必要手段,如果子類想達到職能單一,那麼接口也必須滿足職能單一。相反,如果接口融合了多個不相關的方法,那它的子類就要被迫實作所有方法,盡管有些方法是根本用不到的,這就是接口污染。

潛台詞:拆分,從接口開始。

5.依賴倒置原則:

含義:要求調用者和被調用者都依賴抽象。

面向對象初期的程式,被調用者依賴于調用者,也就是調用者決定被調用者有什麼方法,有什麼實作方式,這種結構在需求變更的時候,會付出很大的代價,甚至推翻重寫。依賴倒置原則要求調用者和被調用者都依賴抽象,線河陽兩者沒有直接的關聯和接觸,在變動的時候,一方的變動不會影響另一方的變動。

潛台詞:面向抽象程式設計,解耦調用和被調用者。

6.迪米特原則:

含義:要求盡量的封裝,盡量的獨立,盡量的使用低級别的通路修飾符。

一個類如果暴露太多私用的方法和字段,會讓調用者很迷茫。并且會給類造成不必要的判斷代碼。是以,我們使用盡量低的通路修飾符,讓外界不知道我們的内部,這也是面向對象的基本思路。這是迪米特原則的一個特性,無法了解類更多的私有資訊。另外,迪米特原則要求類之間的直接聯系盡量的少,兩個類的通路,通過第三個中介類來實作。

潛台詞:不和陌生人說話,有事去中介。

7.組合/聚合複用原則:

含義:如果隻是達到代碼複用的目的,盡量使用組合與聚合,而不是繼承。

繼承的耦合性更大,比如一個父類後來添加實作一個接口或者去掉一個接口,那子類可能會遭到毀滅性的編譯錯誤,但如果隻是組合聚合,隻是引用類的方法,就不會有這種巨大的風險,同時也實作了複用。

潛台詞:我隻是用你的方法,我們不一定是同類。

注意點:

1.高内聚、低耦合和單一職能的“沖突”

實際上,兩者是同一回事。内聚,要求一個類把所有相關的方法放在一起,初看是職能多,但有個“高”,就是要求把聯系非常緊密的功能放在一起,也就是說,從整體看,是一個職能的才放在一起,是以,兩者是不同的表述而已。

2.多個單一職能接口的靈活性和聲明類型問題

如果一個類實作多個接口,那麼這個類應該用哪個接口類型聲明呢?應該是用一個抽象類來繼承多個接口,而實作類來繼承這個抽象類,聲明的時候,類型是抽象類。

3.最少知識原則和中介類泛濫兩種極端情況

迪米特原則要求類中間要用中介來通信,但類多了以後,會造成中介類泛濫的情況,這種情況,我們可以考慮中介模式,用一個總的中介類來實作。當然,設計模式都有自己的缺陷,迪米特原則也不是十全十美,互動類非常繁多的情況下,要适當的犧牲設計原則。

4.繼承群組合聚合複用原則的沖突

繼承也能實作複用,那這個原則是不是要抛棄繼承了?不是的。繼承更注重的是“血統”,也就是什麼類型的,而組合聚合更注重的是借用“技能”。并且,組合聚合中,兩個類是部分與整體的關系,組合聚合可以由多個類的技能組成。在C#和Java中隻有單繼承。這個原則告訴我們,在複用這點上,優先使用組合聚合。

共性問題

1.這麼多設計模式,都要學習和使用麼?

我們隻是掌握總體的原則,然後學習常用的就行了。實際開發中也不是每種設計模式都會經常用到。因為歸根結底,設計模式也好,架構也好,都是為需求服務的,沒有需求業務模型,不能生搬硬套模式,我們在學習時,多學一些總是好的,但隻是為了開闊自己的眼界。

2.設計模式是規範麼?是不是好的程式必須使用設計模式?

嚴格來說,好的程式遵循的是設計原則,而非設計模式。現在就出現很多新的演變出來的模式,這些都是因為出現了新業務的原因,設計模式不是規範,隻是一種借鑒。

3.使用設計模式會不會增加開發難度?

開發階段會的,而且會延長開發時間。但一個項目或産品從開始到結束,開發隻是其中很小的一部分,考慮到維護和擴充成本,才會出現設計模式。從整體考慮,設計模式是減少了開發時間和成本的。