原則一:(SRP:Single responsibility principle)單一職責原則又稱單一功能原則
核心:解耦和增強內聚性(高內聚,低耦合)
描述:
類被修改的機率很大,因此應該專注於單一的功能。如果你把多個功能放在同一個類中,功能之間就形成了關聯,
改變其中一個功能,有可能中止另一個功能,這時就需要新一輪的測試來避免可能出現的問題。
原則二:開閉原則(OCP:Open Closed Principle)
核心思想:對擴展開放,對修改關閉。即在設計一個模塊的時候,應當使這個模
塊可以在不被修改的前提下被擴展。
根據開閉原則,在設計一個軟件系統模塊(類,方法)的時候,應該可以在不修改原有的模塊(修改關閉)的基礎上,能擴展其功能(擴展開放)。
擴展開放:
某模塊的功能是可擴展的,則該模塊是擴展開放的。軟件系統的功能上的可擴展性要求模塊是擴展開放的。
修改關閉:
某模塊被其他模塊調用,如果該模塊的源代碼不允許修改,則該模塊修改關閉的。軟件系統的功能上的穩定性,持續性要求是修改關的。
原則三:里氏替換原則(LSP:Liskov Substitution Principle)
核心:
1.在任何父類出現的地方都可以用他的子類來替代(子類應當可以替換父類並出現在父類能夠出現的任何地方)
子類必須完全實現父類的方法。在類中調用其他類是務必要使用父類或接
口,如果不能使用父類或接口,則說明類的設計已經違背了LSP原則。
2.子類可以有自己的個性。子類當然可以有自己的行爲和外觀了,也就是方
法和屬性
3.覆蓋或實現父類的方法時輸入參數可以被放大。即子類可以重載父類的方法,但輸入參數應比父類方法中的大,這樣在子類代替父類的時候,調用的仍然是父類的方法。即以子類中方法的前置條件必須與超類中被覆蓋的方法的前置條件相同或者更寬鬆。
4.覆蓋或實現父類的方法時輸出結果可以被縮小。
原則四:依賴倒轉原則(DIP:Dependence Inversion Principle)
別名:依賴倒置原則或依賴反轉原則
核心:要依賴於抽象,不要依賴於具體的實現
1.高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象(抽象類或接口)
2.抽象不應該依賴細節(具體實現)
3.細節(具體實現)應該依賴抽象。
三種實現方式:
1.通過構造函數傳遞依賴對象
2.通過setter方法傳遞依賴對象
3.接口聲明實現依賴對象
原則五:接口分離原則(ISP:Interface Segregation Principle)
核心思想:
不應該強迫客戶程序依賴他們不需要使用的方法。
接口分離原則的意思就是:一個接口不需要提供太多的行爲,一個接口應該只提供一種對外的功能,不應該把所有的操作都封裝到一個接口當中.
分離接口的兩種實現方法:
1.使用委託分離接口。(Separation through Delegation)
2.使用多重繼承分離接口。(Separation through Multiple Inheritance)
原則六:合成複用原則(CRP:Composite Reuse Principle)
核心思想:
儘量使用對象組合,而不是繼承來達到複用的目的。該原則就是在一個新的對象裏面使用一些已有的對象,
使之成爲新對象的一部分:新的對象通過向這些對象的委派達到複用已有功能的目的。
複用的種類:
1.繼承
2.合成聚合
注:在複用時應優先考慮使用合成聚合而不是繼承
原則七:迪米特原則(LOD:Law of Demeter)
又叫最少知識原則
核心思想:
一個對象應當對其他對象有儘可能少的瞭解,不和陌生人說話。
(類間解耦,低耦合)意思就是降低各個對象之間的耦合,提高系統的可維護性;在模塊之間只通過接口來通信,
而不理會模塊的內部工作原理,可以使各個模塊的耦合成都降到最低,促進軟件的複用
注:
1.在類的劃分上,應該創建有弱耦合的類;
2.在類的結構設計上,每一個類都應當儘量降低成員的訪問權限;
3.在類的設計上,只要有可能,一個類應當設計成不變;
4.在對其他類的引用上,一個對象對其它對象的引用應當降到最低;
5.儘量降低類的訪問權限;
6.謹慎使用序列化功能;
7.不要暴露類成員,而應該提供相應的訪問器(屬性)
UML統一建模語言,java中七種設計原則
UML統一建模語言。
類與類,類和接口,接口和接口之間的關係。
1、實現關係(一個類實現一個接口)
2、泛化關係(一個類繼承另一個類)
3、關聯(1)、依賴關係:一個類是另一個類的方法局部變量,方法的參數或方法返回值。2)、聚合關係:一個類是另一個類的屬性,是整體和部分的關係。3)、組合關係:一個類是另一個類的屬性,是整體不可分割的一部分,是強聚合。)
4、單一職責:一個類而言,應該僅有一個引起它變化的原因,永遠不要讓一個類存在多個改變的理。一個類只應該做和一個任務相關的業務,不應該把過多的業務放在一個類中完成。
迪米特法則:
一個軟件實體應當儘可能少的與其他實體發生相互作用。

七種設計原則總結
單一職責原則:一個類只應該做和一個職責相關的事情,不要把過多的業務放在一個類中完成。
迪米特法則:軟件實體之間應該做到最少的交互。不要和陌生人說話。調用方只關心他需要使用的方法
接口隔離原則:使用專門的接口,比用統一的接口要好。便於分工,在實現接口時,不應該看到自己不用關心的方法。
開閉原則:軟件實體應該對擴展開放,對修改關閉。開閉原則是設計原則的核心原則,其他的設計原則都是開閉原則表現和補充。實現開閉原則的方法就是抽象。
聚合/組合複用原則。多使用聚合/組合達到代碼的重用,少使用繼承複用。
依賴倒置原則:面向抽象編程,不要面向具體編程。
面向對象七大設計原則
1、 開閉原則
2、 里氏替換原則
3、 單一職責原則
4、 接口隔離原則
5、 依賴倒置原則
6、 迪米特原則
7、組合/聚合複用原則
知識點關聯
學習面向對象的設計模式,是深入面向對象思想的鑰匙,通過大師級的微妙案例,我們可以開闊自己的認知。
在學習面向對象設計七大原則之前,我們要對基本的封裝、繼承、多態思想有足夠的瞭解,對抽象類和接口也要有足夠的編碼能力,因爲設計模式是以上知識點的綜合應用。
另外,在接觸具體的設計模式之前,面向對象的七大設計原則會讓你知道,設計模式出現的必然性和意義所在。
1、 每一種設計思想的精準含義,具體如下:
先從整體認識這七種設計思想。
一、開閉原則:
這一條放在第一位來理解,它的含義是對擴展開放,對修改關閉。解釋一下就是,我們寫完的代碼,不能因爲需求變化就修改。我們可以通過新增代碼的方式來解決變化的需求。
當然,這是一種理想的狀態,在現實中,我們要儘量的縮小這種修改。
再解釋一下這條原則的意義所在,我們採用逆向思維方式來想。如果每次需求變動都去修改原有的代碼,那原有的代碼就存在被修改錯誤的風險,當然這其中存在有意和無意的修改,都會導致原有正常運行的功能失效的風險,這樣很有可能會展開可怕的蝴蝶效應,使維護工作劇增。
說到底,開閉原則除了表面上的可擴展性強以外,在企業中更看重的是維護成本。
所以,開閉原則是設計模式的第一大原則,它的潛臺詞是:控制需求變動風險,縮小維護成本。
以下幾種原則,都是爲此原則服務的。
二、里氏替換選擇:
此原則的含義是子類可以在任何地方替換它的父類。解釋一下,這是多態的前提,我們後面很多所謂的靈活,都是不改變聲明類型的情況下,改變實例化類來完成的需求變更。當然,繼承的特性看似天然就滿足這個條件。但這裏更注重的是繼承的應用問題,我們必須保證我們的子類和父類劃分是精準的。
里氏替換原則的潛臺詞是:儘量使用精準的抽象類或者接口。
三、單一職責原則:
單一職責的含義是:類的職責單一,引起類變化的原因單一。解釋一下,這也是靈活的前提,如果我們把類拆分成最小的職能單位,那組合與複用就簡單的多了,如果一個類做的事情太多,在組合的時候,必然會產生不必要的方法出現,這實際上是一種污染。
舉個例子,我們在繪製圖案的時候,用“點”組成圖和用“直線”組成圖,哪個更靈活呢?一定是“點”,它可以繪製任何圖形,而直線只能繪製帶有直線條的圖案,它起碼無法畫圓。
單一職責的潛臺詞是:拆分到最小單位,解決複用和組合問題。
四、接口隔離原則:
接口隔離原則可以說是單一職責的必要手段,它的含義是儘量使用職能單一的接口,而不使用職能複雜、全面的接口。很好理解,接口是爲了讓子類實現的,如果子類想達到職能單一,那麼接口也必須滿足職能單一。
相反,如果接口融合了多個不相關的方法,那它的子類就被迫要實現所有方法,儘管有些方法是根本用不到的。這就是接口污染。
接口隔離原則的潛臺詞是:拆分,從接口開始。
五、依賴倒置原則:
想要理解依賴倒置原則,必須先理解傳統的解決方案。面相對象的初期的程序,被調用者依賴於調用者。也就是調用者決定被調用者有什麼方法,有什麼樣的實現方式,這種結構在需求變更的時候,會付出很大的代價,甚至推翻重寫。
依賴倒置原則就是要求調用者和被調用者都依賴抽象,這樣兩者沒有直接的關聯和接觸,在變動的時候,一方的變動不會影響另一方的變動。
其實,依賴倒置和前面的原則是相輔相成的,都強調了抽象的重要性。
依賴倒置的潛臺詞是:面向抽象編程,解耦調用和被調用者。
六、迪米特原則:
迪米特原則要求儘量的封裝,儘量的獨立,儘量的使用低級別的訪問修飾符。這是封裝特性的典型體現。
一個類如果暴露太多私用的方法和字段,會讓調用者很茫然。並且會給類造成不必要的判斷代碼。所以,我們使用盡量低的訪問修飾符,讓外界不知道我們的內部。這也是面向對象的基本思路。這是迪米特原則的一個特性,無法瞭解類更多的私有信息。
另外,迪米特原則要求類之間的直接聯繫儘量的少,兩個類的訪問,通過第三個中介類來實現。
迪米特原則的潛臺詞是:不和陌生人說話,有事去中介。
七、組合/聚合複用原則:
此原則的含義是,如果只是達到代碼複用的目的,儘量使用組合與聚合,而不是繼承。這裏需要解釋一下,組合聚合只是引用其他的類的方法,而不會受引用的類的繼承而改變血統。
繼承的耦合性更大,比如一個父類後來添加實現一個接口或者去掉一個接口,那子類可能會遭到毀滅性的編譯錯誤,但如果只是組合聚合,只是引用類的方法,就不會有這種巨大的風險,同時也實現了複用。
組合聚合複用原則的潛臺詞是:我只是用你的方法,我們不一定是同類。
2、 在學習面向對象七大設計原則時需要注意以下幾點:
a) 高內聚、低耦合和單一職能的“衝突”
實際上,這兩者是一回事。內聚,要求一個類把所有相關的方法放在一起,初看是職能多,但有個“高”,就是要求把聯繫非常緊密的功能放在一起,也就是說,從整體看,是一個職能的才能放在一起,所以,兩者是不同的表述而已。
這裏很多人理解成複合類,但複合類不是高內聚,而是雜亂的放在一起,是一種設計失誤而已。
b) 多個單一職能接口的靈活性和聲明類型問題
如果一個類實現多個接口,那麼這個類應該用哪個接口類型聲明呢?應該是用一個抽象類來繼承多個接口,而實現類來繼承這個接口。聲明的時候,類型是抽象類。
c) 最少知識原則和中介類氾濫兩種極端情況
這是另一種設計的失誤。迪米特原則要求類之間要用中介來通訊,但類多了以後,會造成中介類氾濫的情況,這種情況,我們可以考慮中介模式,用一個總的中介類來實現。
當然,設計模式都有自己的缺陷,迪米特原則也不是十全十美,交互類非常繁多的情況下,要適當的犧牲設計原則。
d) 繼承和組合聚合複用原則的“衝突”
繼承也能實現複用,那這個原則是不是要拋棄繼承了?不是的。
繼承更注重的是“血統”,也就是什麼類型的。而組合聚合更注重的是借用“技能”。並且,組合聚合中,兩個類是部分與整體的關係,組合聚合可以由多個類的技能組成。在C#和Java中只有單繼承。
這個原則不是告訴我們不用繼承了,都用組合聚合,而是在“複用”這個點上,我們優先使用組合聚合。
面向對象設計原則的共性問題:
1、這麼多設計模式,都要學習和使用麼?
答:我們只是掌握總體的原則,然後學習常用的就行了。實際開發中也不是每種設計模式都會經常用到。因爲歸根結底,設計模式也好,架構也好,都是爲需求服務的,沒有需求業務模型,不能生搬硬套模式。我們在學習的時候,多學一些總是好的,但只是爲了開闊自己的眼界。
2、設計模式是規範麼?是不是好的程序必須用設計模式?
答:嚴格來說,好的程序遵循的是設計原則,而非設計模式。現在就出現很多新的演變出來的模式,這些都是因爲出現了新業務的原因,設計模式不是規範,只是一種借鑑。
3、使用設計模式會不會增加開發難度?
答:開發階段會的,而且會延長開發時間。但一個項目或產品從開始到結束,開發只是其中很小的一部分,考慮到維護和擴展成本,纔會出現設計模式。從整體考慮,設計模式是減少了開發時間和成本的。
關於七種面向對象設計原則
面向對象設計原則是我們用於評價一個設計模式的使用效果的重要標準之一。
下面我給大家介紹一下七種設計原則各是什麼,以及其定義:
單一職責原則 定義:一個類只負責一個領域的相應職責
開閉原則 定義:軟件實體應對擴展開放,而對修改關閉
里氏替換原則 定義:所有引用基類的對象能夠透明的使用其子類的對象
依賴倒轉原則 定義:抽象不應該依賴於細節,細節依賴於抽象
接口隔離原則 定義:使用多個專門的接口,而不是使用單一總接口
合成複用原則 定義:儘量使用對象組合,而不是繼承來達到複合目的
迪米特法則 定義:一個軟件實體應當儘可能少的與其它實體發生相互作用
其中比較常用的是紅色字體,藍色字體僅次,黑色字體基本不使用。
里氏替換原則:父類出現的方法,子類一定可以替換。如果子類不能完整實現父類方法,或者父類的方法在子類中已經發生了畸變,那麼就要斷開父子關係。採用依賴、聚合、組合等關係替代繼承。里氏替換原則可以用於檢測兩個類是否具有父子關係。
7種常用的面向對象設計原則
設計原則名稱
定義
使用頻率
單一職責原則
(Single Responsibility Principle, SRP)
一個類只負責一個功能領域中的相應職責
★★★★☆
開閉原則
(Open-Closed Principle, OCP)
軟件實體應對擴展開放,而對修改關閉
★★★★★
里氏代換原則
(Liskov Substitution Principle, LSP)
所有引用基類對象的地方能夠透明地使用其子類的對象
★★★★★
依賴倒轉原則
(Dependence Inversion Principle, DIP)
抽象不應該依賴於細節,細節應該依賴於抽象
★★★★★
接口隔離原則
(Interface Segregation Principle, ISP)
使用多個專門的接口,而不使用單一的總接口
★★☆☆☆
合成複用原則
(Composite Reuse Principle, CRP)
儘量使用對象組合,而不是繼承來達到複用的目的
★★★★☆
迪米特法則
(Law of Demeter, LoD)
一個軟件實體應當儘可能少地與其他實體發生相互作用
★★★☆☆