前言
《設(shè)計模式自習(xí)室》系列,顧名思義,本系列文章帶你溫習(xí)常見的設(shè)計模式。
但是,在開篇中,我想要先整體的介紹下設(shè)計模式,讓大家知道為什么要學(xué)習(xí)設(shè)計模式。
所以這篇文章的主要內(nèi)容是:
- 我對設(shè)計模式的理解
- 設(shè)計模式的至高目標:解耦(高內(nèi)聚低耦合)
- 設(shè)計模式的分類
- 設(shè)計模式遵循的設(shè)計原則
- 為什么我寫代碼常常用不到設(shè)計模式?
為什么我們需要設(shè)計模式?
我對設(shè)計模式的理解
當我剛剛接觸程序,最初聽到“設(shè)計模式”這四個字的時候,我常常會思考一個問題,這個東西為什么這么拗口。就像我當初聽到“離散數(shù)學(xué)”,“具體數(shù)學(xué)”一樣,有種摸不著頭腦的感覺。
帶著這種疑問,我嘗試看了幾篇介紹設(shè)計模式的文章,它們都對設(shè)計模式進行了這樣的介紹:
軟件設(shè)計模式(Design pattern),又稱設(shè)計模式,是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計經(jīng)驗的總結(jié)。 使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。
看完之后,我更加摸不著頭腦了。看著什么單例模式,責(zé)任鏈模式的代碼,感覺老師從來就沒提過這些,為什么要把代碼寫成這樣,好好的寫完自己想要的功能不就好了嘛???
是的,設(shè)計模式,對于入門程序員來說,確實有點空中樓閣,尤其是對于沒接觸過大型項目的人而言,這些代碼是如此的陌生,甚至有點“故弄玄虛”。
但是,生活往往就是有這么多“但是”!當你逐漸入門了程序編寫,接觸到了大型的,功能復(fù)雜的,需要多人合作的代碼后,再回頭看設(shè)計模式,往往就有了越來越清晰的認識。
隨著我的經(jīng)驗積累,再回來復(fù)習(xí)設(shè)計模式,常常有醒悟的感覺。接下來就說說我對設(shè)計模式的認知:
設(shè)計模式的英文是什么?Design pattern,這是一個非常之準確的詞匯,個人認為比中文翻譯好太多了。
Patten中文釋義:. n. 模式;圖案;樣品. vt. 模仿
pattern往往意味著是一種既定的準則,從它的動詞可以看到,他有模仿的意思,也就是說,這樣的代碼設(shè)計,是一系列前人留下的經(jīng)驗,只要跟著這樣寫代碼,往往能夠讓你的代碼,更加簡潔,更加健壯,更加優(yōu)雅!
我覺得他應(yīng)該有個意譯的名字,叫做:代碼設(shè)計的最佳實踐!
是不是很耳熟,還記得最近很火的《阿里巴巴Java開發(fā)手冊》,以及經(jīng)典的《Effective Java》嗎?他們都是屬于經(jīng)驗總結(jié)型的知識,目的是幫助程序員寫出更優(yōu)雅的代碼!
如果你沒聽過上面的幾本書,沒關(guān)系,當然,你也可以看看我之前的文章 《阿里巴巴Java開發(fā)手冊》閱讀筆記,大概了解下他們的內(nèi)容是什么樣的,你就會理解我說的“他們是一個類型的”。
高內(nèi)聚低耦合
設(shè)計模式是一種代碼設(shè)計思路,其最最本質(zhì)的目的是為了解耦,延伸一點的話,還有為了可擴展性和健壯性,但是這都是建立在解耦的基礎(chǔ)之上。
有同學(xué)要問了,“解耦”是什么意思呢?請先看下面兩個概念:
高內(nèi)聚
系統(tǒng)中A、B兩個模塊進行交互,如果修改了A模塊,不影響模塊B的工作,那么認為A是高度內(nèi)聚的。
低耦合
那么當B發(fā)生改變時,A模塊仍然可以正常工作,那么就認為A與B是低耦合的。
所以解耦,本質(zhì)上就是讓不同的代碼塊各司其職,互不干擾!
設(shè)計模式的分類
創(chuàng)建型模式
創(chuàng)建型模式將創(chuàng)建對象的過程進行了抽象,也可以理解為將創(chuàng)建對象的過程進行了封裝,作為客戶程序僅僅需要去使用對象,而不再關(guān)系創(chuàng)建對象過程中的邏輯。
- 簡單工廠模式(Simple Factory):簡單工廠模式不是GoF總結(jié)出來的23種設(shè)計模式之一
- 工廠方法模式(Factory Method)
- 抽象工廠模式(Abstract Factory)
- 創(chuàng)建者模式(Builder)
- 原型模式(Prototype)
- 單例模式(Singleton)
結(jié)構(gòu)型模式
結(jié)構(gòu)型模式是為解決怎樣組裝現(xiàn)有的類,設(shè)計它們的交互方式。例如:擴展性(外觀、組成、代理、裝飾)、封裝(適配器、橋接)。因為如何設(shè)計對象的結(jié)構(gòu)、繼承和依賴關(guān)系會影響到后續(xù)程序的維護性、代碼的健壯性、耦合性等。
- 外觀模式/門面模式(Facade門面模式)
- 適配器模式(Adapter)
- 代理模式(Proxy)
- 裝飾模式(Decorator)
- 橋梁模式/橋接模式(Bridge)
- 組合模式(Composite)
- 享元模式(Flyweight)
行為型模式
行為模式刻劃了在程序運行時難以跟蹤的復(fù)雜的控制流,進一步可分為行為類模式和行為對象模式。
行為類模式使用繼承機制在類間分派行為。
行為對象模式使用對象聚合來分配行為。一些行為對象模式描述了一組對等的對象怎樣相互協(xié)作以完成其中任何一個對象都無法單獨完成的任務(wù)。
- 模板方法模式(Template Method)
- 觀察者模式(Observer)
- 狀態(tài)模式(State)
- 策略模式(Strategy)
- 職責(zé)鏈模式(Chain of Responsibility)
- 命令模式(Command)
- 訪問者模式(Visitor)
- 調(diào)停者模式(Mediator)
- 備忘錄模式(Memento)
- 迭代器模式(Iterator)
- 解釋器模式(Interpreter)
三者之間的區(qū)別和聯(lián)系
創(chuàng)建型模式提供生存環(huán)境,結(jié)構(gòu)型模式提供生存理由,行為型模式提供如何生存。
創(chuàng)建型模式為其他兩種模式使用提供了環(huán)境。
結(jié)構(gòu)型模式側(cè)重于接口的使用,它做的一切工作都是對象或是類之間的交互,提供一個門。
行為型模式顧名思義,側(cè)重于具體行為,所以概念中才會出現(xiàn)職責(zé)分配和算法通信等內(nèi)容。
設(shè)計原則
設(shè)計模式是優(yōu)雅的代碼實現(xiàn),所以會講究標準的設(shè)計原則,常用的設(shè)計原則如下:
- 開閉原則: 對擴展開放,對修改關(guān)閉
- 里氏轉(zhuǎn)換原則: 子類繼承父類,單獨完全可以運行
- 依賴倒轉(zhuǎn)原則: 引用一個對象,如果這個對象有底層類型,直接引用底層類型
- 接口隔離原則: 每一個接口應(yīng)該是一種角色
- 合成/聚合復(fù)用原則: 新的對象應(yīng)使用一些已有的對象,使之成為新對象的一部分
- 迪米特原則: 一個對象應(yīng)對其他對象有盡可能少的了解
為什么我寫代碼常常用不到設(shè)計模式?
這一點,是我臨時加上的,因為我之前也有這樣的困惑。看了這么多設(shè)計模式,為什么我日常使用中根本就不會想到去用呢?我想給出幾點回答:
第一,我們?nèi)粘i_發(fā)中,經(jīng)常是使用框架在構(gòu)造大型的項目,框架已經(jīng)為我們考慮到了太多的設(shè)計,已經(jīng)讓我們開箱即用。所以我們常常只需要CRUD(增刪改查)。其實框架的源碼中,使用到了非常多的設(shè)計模式,這也是為什么很多大牛在推薦我們看某某框架的源碼前,常常建議我們先看設(shè)計模式。否則看源碼的時候,會非常的吃力,因為不知道為什么會這樣寫代碼
第二,設(shè)計模式的使用往往在你的編程經(jīng)驗積累到一定程度后,在遇到了大量的問題后,你會想著去進行合理的代碼結(jié)構(gòu)設(shè)計來解決一些常常會遇到的問題,這時候,你就會慢慢的想到使用設(shè)計模式了!所以不要急,你可以先不用強行往自己的項目上放設(shè)計模式,但一定要先了解各種設(shè)計模式
第三,如果你急著想要上手實踐設(shè)計模式,那么,做一個完全不依賴大型框架的項目吧,可以是一個工具類,可以是一個小功能腳本,只要不依賴那些復(fù)雜的框架,很快你就能發(fā)現(xiàn)你代碼中可以應(yīng)用設(shè)計模式的地方,別問我怎么知道的,快去自己造一個輪子吧!
總結(jié)
本文概括介紹了下設(shè)計模式到底是個什么東西,在接下來的文章中,我們會一個個設(shè)計模式來介紹,敬請期待!