二十三種設計模式-六大原則


二十三種設計模式

一、創建型:

單例模式、工廠模式、抽象工廠模式、原型模式、建造者模式;

 

二、結構型:

代理模式,裝飾器模式、適配器模式、外觀模式、組合模式、享元模式、橋梁模式;

 

 

三、行為型:

策略模式、責任鏈模式、命令模式、中介者模式、模板方法模式、迭代器模式、訪問者模式、觀察者模式、解釋器模式、備忘錄模式、狀態模式。

 

 

三類設計模式的特點:

 

 

六大原則

一、開放封閉(簡稱開閉)原則

Open-Close Principle(OCP):一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。目的就是保證程序的擴展性好,易於維護和升級。

開閉原則被稱為面向對象設計的基石,實際上,其他原則都可以看作是實現開閉原則的工具和手段。意思就是:軟件對擴展應該是開放的,對修改是封閉的,通俗來說就是,開發一個軟件時,應該對其進行功能擴展,而在進行這些擴展時,不需要對原來的程序進行修改。

好處是:軟件可用性非常靈活,擴展性強。需要新的功能時,可以增加新的模塊來滿足新需求。另外由於原來的模塊沒有修改,所以不用擔心穩定性的問題。

二、單一職責原則

Single-Responsibilitiy Principle(SRP):對一個類而言,應該僅有一個引起它變化的原因。如果存在多於一個動機去改變一個類,那么這個類就具有多於一個的職責,就應該把多余的職責分離出去,再去創建一些類來完成每一個職責。

舉個例子:一個人身兼數職,而這些事情相關性不大,甚至有沖突,那他就無法很好的解決這些問題職責,應該分到不同的人身上去做。

單一職責原則是實現高內聚低耦合的最好方法,沒有之一。

 1 class CellPhone:
 2   
 3     def call(string person):
 4       //打電話
 5       pass
 6     def hangup():
 7      //掛斷電話
 8         pass
 9 
10     def sendMessage(string person):
11     //發送信息
12         pass
13     def receiveMessage():
14     //接受信息
15         pass

上面的手機類雖然符合人們對手機的認識,但是實際上卻擁有兩個不同的職責:打電話、掛斷電話和發短信、接受信息,因此引起它變化的原因就有多個,是比較脆弱的設計,應該將兩種行為分離。

三、里氏代換原則

Liskov Substitution Principle:子類可以擴展父類的功能,但是不能改變父類原有的功能。

在第一條原則開放封閉原則中,主張“抽象”和“多態”。維持設計的封裝性“抽象”是語言提供的功能,“多態”由繼承語意實現。因此如何去度量繼承關系中的質量?

答案是:繼承必須明確確保超類(父類)所擁有的性質在子類中仍然成立。

在面向對象的思想中,一個對象就是一組狀態和一系列行為的組合體。狀態是對象的內在特性,行為是對象的外在特性。LSP表述的就是在同一繼承體系中的隊形應該具有共同的行為特征。

 1 class bird:
 2     color = ''
 3     weight = ''
 4     def eat():
 5         pass
 6     def fly():
 7         print("fly")
 8         
 9 class chicken(bird):
10     def fly():
11         print("can not fly")

在上述例子中,父類也就是對象鳥有兩個行為也就是方法:eat()和fly(),在子類chicken中這兩個行為也應該成立,但是現實中chicken是不能飛的,因此chicken中的fly()方法覆蓋了父類中的方法。違反了VSP。

四、依賴倒置原則

Dependence Inversion Principle(DIP):是一個類與類之間的調用規則。這里的依賴就是代碼中的耦合。高層模塊不應該依賴底層模塊,二者都應該依賴其抽象了;抽象不依賴細節;細節應該依賴抽象。接口編程。

主要思想就是:如果一個類中的一個成員或者參數成為一個具體的類型,那么這個類就依賴這個具體類型。如果在一個繼承結構中,上層類中的一個成員或者參數為一個下層類型,那么就是這個繼承結構高層依賴底層,就要盡量面向抽象或者接口編程。

舉例:存在一個Driver類,成員為一個Car對象,還有一個driver()方法,Car對象中有兩個方法start()與stop()。顯然Driver依賴Car,也就是說Driver類調用了Car類中的方法。但是當增加Driver類對於Bus類的支持時(司機有需要開公交車),就必須更改Driver中的代碼,就破壞了開放封閉原則。根本原因在於高層的的Driver類與底層的Car類僅僅的耦合在一起的。解決方法之一就是:對Car類和Bus類進行抽象,引入抽象類Automoble。而Car和Bus則是對Automobile的泛化。

經過這樣的改造發現,原本的高層依賴底層,變成了高層與底層同時依賴抽象。這就是依賴倒轉原則的本質。

 

五、接口隔離原則

接口隔離原則(Interface Segregation Principle):用於恰當的划分角色和接口,具有兩種含義:1、用戶不應該依賴它不需要的借口;2、類間的依賴關系應該建立在最小的的接口上。

將這兩個定義概括為一句話:建立單一接口,代替龐大臃腫的接口。通俗來說就是:接口盡量細化,同時保證接口中的方法盡量的少。一個接口中包含太多的行為時,會導致它們與客戶端的不正常依賴關系,要做的就是分離接口,從而實現解耦。

回到上述的單一職責原則,要求行為分離接口接口細化,感覺有些相同。但實際上,單一職責原則要求類與接口的職責單一,注重的是職責,沒有要求接口盡量的少。

在接口隔離原則中,要求盡量使用多個專門的接口。專門的接口也就是提供給多個模塊的接口。提供給幾個模塊就應該有幾個接口,而不是建立一個臃腫龐大的接口,所有的模塊都可以訪問。

但是接口的設計是有限度的。接口的設計粒度越小系統越靈活,這是事實,但是接口太多這也就使得結構復雜,維護難度大。因此實際中,怎樣把握就靠開發的經驗和常識了。

六、迪米特原則

Law of Demeter(最小知識原則):一個對象應該對其他對象有最少的了解。通俗來說就是,一個類對自己需要耦合或者調用的類知道的最少,你類內部怎么復雜,我不管,那是你的事,我只知道你有那么多公用的方法,我能調用。

迪米特原則不希望類與類之間建立直接的接觸。如果真的需要有聯系,那么就通過它們的友元類來傳達。舉例來說:你需要買房子了,現在存在三座合適的樓盤A,B,C,但是你不必直接去樓盤買樓,而是在售樓處去了解情況。這樣就減少了你(購房者)與樓盤兩個類之間耦合。

但是應用迪米特原則很可能會造成一個后果:系統會存在大量的中介類,這些類(如上面的售樓處類)之所以存在是為了傳遞類之間的相互調用關系,這就一定會程度上增加了系統的復雜度。

迪米特原則核心觀念就是:類間解耦,弱耦合。

源碼地址:https://github.com/weilanhanf/PythonDesignPatterns

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM