用現實生活中實例解釋說明設計模式六大基本原則


設計模式分類

  • 創建型模式

    用於描述“怎樣創建對象”,它的主要特點是“將對象的創建與使用分離”。GoF(四人組)書中提供了單例、原型、工廠方法、抽象工廠、建造者等 5 種創建型模式。

  • 結構型模式

    用於描述如何將類或對象按某種布局組成更大的結構,GoF(四人組)書中提供了代理、適配器、橋接、裝飾、外觀、享元、組合等 7 種結構型模式。

  • 行為型模式

    用於描述類或對象之間怎樣相互協作共同完成單個對象無法單獨完成的任務,以及怎樣分配職責。GoF(四人組)書中提供了模板方法、策略、命令、職責鏈、狀態、觀察者、中介者、迭代器、訪問者、備忘錄、解釋器等 11 種行為型模式。

軟件設計原則

​ 在軟件開發中,為了提高軟件系統的可維護性和可復用性,增加軟件的可擴展性和靈活性,程序員要盡量根據6條原則來開發程序,從而提高軟件開發效率、節約軟件開發成本和維護成本。

開閉原則

對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是為了使程序的擴展性好,易於維護和升級。

想要達到這樣的效果,需要使用接口和抽象類。因為抽象靈活性好,適應性廣,只要抽象的合理,可以基本保持軟件架構的穩定。而軟件中易變的細節可以從抽象派生來的實現類來進行擴展,當軟件需要發生變化時,只需要根據需求重新派生一個實現類來擴展就可以了。

以博客園主題為例介紹開閉原則的應用:

用戶可以根據自己的喜愛更換自己的博客園主題。這些主題有共同的特點,可以為其定義一個抽象類(Theme),而每個具體的主題×××Theme是其子類。用戶可以根據需要選擇或者增加新的主題,而不需要修改原代碼,所以它是滿足開閉原則的。

里氏替換原則

里氏替換原則(The Liskov Substitution Principle,LSP)是由Barbara Liskov女士於1988年提出的,其定義為:“如果對於類型S的每個對象O1存在類型T的對象O2,那么對於所有定義了T的程序P來說,當用O1替換 O2並且S是T的子類型時,P的行為不會改變”。

里氏代換原則:任何基類可以出現的地方,子類一定可以出現。通俗理解:子類可以擴展父類的功能,但不能改變父類原有的功能。換句話說,子類繼承父類時,除添加新的方法完成新增功能外,盡量不要重寫父類的方法。里氏代換原則是對開閉原則的補充,原則上講子類對象介紹給父類對象,也可以說子類替換父類,並且出現在父類能夠出現的任何地方代替父類對象

如果通過重寫父類的方法來完成新的功能,這樣寫起來雖然簡單,但是整個繼承體系的可復用性會比較差,特別是運用多態比較頻繁時,程序運行出錯的概率會非常大。

里氏替換——鴕鳥非鳥

這里我們以另一個理解里氏替換原則的經典例子“鴕鳥非鳥”來做示例。生物學中對於鳥類的定義是“恆溫動物,卵生,全身披有羽毛,身體呈流線形,有角質的喙,眼在頭的兩側。前肢退化成翼,后肢有鱗狀外皮,有四趾”。從生物學角度來看,鴕鳥肯定是一種鳥,是一種繼承關系。A需求期望鳥類提供與飛翔有關的行為,即使鴕鳥跟普通的鳥在外觀上就是100%的相像,但在A需求范圍內,鴕鳥在飛翔這一點上跟其它普通的鳥是不一致的,它沒有這個能力,所以,鴕鳥類無法從鳥類派生,鴕鳥不是鳥。B需求期望鳥類提供與羽毛有關的行為,那么鴕鳥在這一點上跟其它普通的鳥一致的。雖然它不會飛,但是這一點不在B需求范圍內,所以,它具備了鳥類全部的行為特征,鴕鳥類就能夠從鳥類派生,鴕鳥就是鳥。從A來看,鴕鳥和鳥之間的繼承關系又可能不成立。那么,鴕鳥和鳥之間到底是不是繼承關系如何判斷呢?這需要根據用戶需求來判斷。

如果父類A和子類B之間的關系違反了里氏替換原則,那么A和B就不適合設計為繼承關系。我們就要重新設計二者之間的關系。設計方案有兩種,需要根據具體情況進行選擇:

  • 創建一個新的抽象類或者接口,作為兩個具體類的基類。將具體類A和B的共同行為轉移到C中,從而解決A和B行為不一致的問題。

  • 將B到A的繼承關系改為委托關系。具體參考組合/聚合復用原則。

依賴倒轉原則

針對接口編程,依賴於抽象而不依賴於具體。簡單的說就是要求對抽象進行編程,不要對實現進行編程,這樣就降低了客戶與實現模塊間的耦合。

依賴倒轉——組裝電腦

現要組裝一台電腦,需要配件cpu,硬盤,內存條。只有這些配置都有了,計算機才能正常的運行。選擇cpu有很多選擇,如Intel,AMD等,硬盤可以選擇希捷,西數等,內存條可以選擇金士頓,海盜船等。如果組裝的電腦的cpu只能是Intel的,內存條只能是金士頓的,硬盤只能是希捷的,這對用戶肯定是不友好的,用戶有了機箱肯定是想按照自己的喜好,選擇自己喜歡的配件。

根據依賴倒轉原則進行改進:我們只需要修改Computer類,讓Computer類依賴抽象(各個配件的接口),而不是依賴於各個組件具體的實現類。

接口隔離原則

使用多個隔離的接口,而非單個接口;一個類對另一個類的依賴應該建立在最小的接口上。

下面看一個例子來理解接口隔離原則

接口隔離——空調

一般空調具有制冷制熱的功能,而有的單冷式空調只有制冷功能,如果只有制冷制熱一個接口,則違背了接口隔離原則。此時應該抽象出制冷制熱兩個接口,而不是只抽象出制冷制熱這一個接口。

迪米特法則

最少知道原則是指:一個實體應當盡量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。

只和你的直接朋友交談,不跟“陌生人”說話(Talk only to your immediate friends and not to strangers)。

其含義是:如果兩個實體無須直接通信,那么就不應當發生直接的相互調用,可以通過第三方轉發該調用。其目的是降低類之間的耦合度,提高模塊的相對獨立性。

迪米特法則中的“朋友”是指:當前對象本身、當前對象的成員對象、當前對象所創建的對象、當前對象的方法參數等,這些對象同當前對象存在關聯、聚合或組合關系,可以直接訪問這些對象的方法。

迪米特法則——演員與經紀人的關系

演員由於活動繁忙,所以許多日常事務由經紀人負責處理,如和粉絲見面會,安排檔期。這里的經紀人是明星的朋友,而粉絲和媒體公司是陌生人,所以適合使用迪米特法則。

合成復用原則

合成復用原則是指:盡量先使用組合或者聚合等關聯關系來實現,其次才考慮使用繼承關系來實現。

通常類的復用分為繼承復用和合成復用兩種。

繼承復用雖然有簡單和易實現的優點,但它也存在以下缺點:

  1. 繼承復用破壞了類的封裝性。因為繼承會將父類的實現細節暴露給子類,父類對子類是透明的,所以這種復用又稱為“白箱”復用。
  2. 子類與父類的耦合度高。父類的實現的任何改變都會導致子類的實現發生變化,這不利於類的擴展與維護。
  3. 它限制了復用的靈活性。從父類繼承而來的實現是靜態的,在編譯時已經定義,所以在運行時不可能發生變化。

采用組合或聚合復用時,可以將已有對象納入新對象中,使之成為新對象的一部分,新對象可以調用已有對象的功能,它有以下優點:

  1. 它維持了類的封裝性。因為成分對象的內部細節是新對象看不見的,所以這種復用又稱為“黑箱”復用。

  2. 對象間的耦合度低。可以在類的成員位置聲明抽象。

  3. 復用的靈活性高。這種復用可以在運行時動態進行,新對象可以動態地引用與成分對象類型相同的對象。

    合成復用原則——網球拍

網球拍有鋁和碳兩種結構,又有多種顏色,如果在抽象類網球拍中同時定義顏色和結構,則會衍生出紅色鋁結構網球拍,藍色鋁結構網球拍,紅色碳結構網球拍,藍色碳結構網球拍等等,我們可以看到使用繼承復用產生了很多子類,如果現在又有新的結構或者新的顏色的話,就需要再定義新的類。我們試着將繼承復用改為聚合復用看一下。可以只在抽象類中保留結構屬性,新建一個顏色接口,讓自類實現不同的顏色接口。


免責聲明!

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



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