在我我的看來,模式通常是指內容會有邊界(Border)或有比較固定內容(Fixed Content)的指導性東西,相似於路走多了就進而造成了路,這個路是有明顯邊界的和指導性的,因此我的理解的設計模式是特定問題的經常使用指導解決方案。編程
設計模式是高層次的解決方案,它要求我的在碰到問題時,不要過多關注問題的細節,將問題泛化和抽象化剝離出問題的核心,進而匹配看是否符合衆多設計模式的使用場景而選用。因此設計模式描述的是:在各類狀況下要選擇什麼樣的方案來解決問題。設計模式
項目中合理地運用設計模式能夠完美地解決不少問題,每種模式都在描述一個在咱們周圍不斷重複發生的問題,以及該問題的核心解決方案。設計模式能夠貫穿在開發乃至重構的過程當中,使代碼處於優雅且複用的狀態以加強軟件設計的適應變化能力。這也是設計模式的目的:提升代碼可重用性和可靠性,並使代碼條理清晰、易於理解、易於維護。框架
根據GOF《設計模式》著做中所說,設計模式能夠分紅三組:建立型(Creational),結構型(Structural),行爲型(Behavioral),共23種。函數
設計模式是複雜的,在引用前要衡量是否有必要給項目引入額外的複雜性。這要求使用者衡量實現某種模式所需的時間與該模式可以帶來的效益。測試
不要在不瞭解設計模式的狀況下使用他們。編碼
使用者需有強大的歸納能力,問題抽象出來都錯了,談何使用?spa
爲何要提倡設計模式呢?上面提到了設計模式的目的是爲了代碼複用,增長可維護性。那麼怎麼才能讓開發人員輕鬆寫出可讀性和可維護性高的程序呢?設計
Martin(Uncle Bob)提出了五項原則,這五個原則被稱爲S.O.L.I.D原則(首字母縮寫):對象
做爲開發者,想必你們都有這樣的經驗,一個方法參雜越多的交叉業務,它的定義就越不明確,複用性就越低。小至方法,大至模塊,承擔的職責越多,就等於把這些職責耦合在一塊兒,它被複用的可能性就越小。當一個類具備了多項職責,它被更改的可能性也會增長,當其中一個職責發生變化時,可能會影響其餘職責的運做,而每一次因爲職責變化發生的改動,也會使得bug產生的風險增長。blog
因此SRP強調的是:引發類變化的因素永遠不要多於一個。這意味着在設計須要的類時,須要考慮使得每一個類被設計出來都只有一個目的(或主要目的)。但這並不意味着每一個類只能有一個方法,應該是該類中全部的方法都要圍繞着該類所描述的主要功能。至於那些有多個職責的類,應該被從新封裝成新的類。
該原則強調的是:一個軟件實體(指的類、函數、模塊等)應該對擴展開放,對修改關閉。即每次發生變化時,要經過添加新的代碼來加強現有類型的行爲,而不是修改原有的代碼。
爲何要這樣呢?咱們都有這樣的經歷,在接手已經在正式上線的項目時,當須要面對新的需求時,咱們首要的任務應該是儘可能保證系統的設計框架是穩定的。對於一個功能,通常不會由於新功能的緣由而去改變以前已經穩定的功能,由於若是你改變它,極可能你的改變會引起系統的崩潰。
OCP提倡的是:你須要一些額外功能,你應該擴展這個類而不是修改它。使用這種方式,現有系統不會看到因爲新變化的所帶來的影響。同時,你只須要測試新建立的類。與SRP同樣,該原理經過儘量減小對現有代碼的更改來下降引入新錯誤的風險。
符合開閉原則的最好方式是提供一個固有的接口(或抽象類),爲系統提供一個相對穩定的抽象層,而後讓全部可能發生變化的類實現該接口,讓固定的接口與相關對象進行交互,這樣若是須要修改系統的行爲,只需在抽象層進行新增業務方法,而後增長新的具體類來實現新的業務功能便可。
里氏替換原則(LSP)聲明:全部引用基類的地方必須能使用其子類的對象。也就是說任何基類能夠被調用的地方,子類也必定能夠被調用。
在軟件開發過程當中,只有當子類替換掉父類後,此時軟件的功能不受影響時,父類才能真正地被複用,而子類也能夠在父類的基礎上添加新的行爲。舉個例子:我喜歡運動,那能推斷出我必定喜歡跑步,由於跑步是運動的一種;可是從我喜歡跑步卻不能推斷我喜歡運動,由於我並不喜歡蹦極,雖然它也是運動的一種。
接口分離原則:使用多個專門的接口比使用單一的總接口要好。也就是說不要讓一個單一的接口承擔過多的職責,而應把每一個職責分離到多個專門的接口中,進行接口分離。
咱們應該都有這樣的經歷,在一個大的業務類型接口中,定義了很是多的方法,當業務須要在該接口添加新方法時,全部實現該接口的類都要去實現該方法,這樣就會致使即便我負責的業務跟你新加的方法沒有太大關係,我也得去實現你的方法,而且因爲須要實現新的方法,致使客戶端會暴露這個方法。
根據接口分離原則,推薦的實現的方式應該是:把大的接口拆分,讓大類實現多個更小的接口,根據用途對功能進行分組。依賴關係與那些相關聯用於鬆耦合,增長健壯性,靈活性以及可複用性。咱們須要注意控制接口的粒度,接口不能過小,若是過小會致使系統中接口氾濫,不利於維護;接口也不能太大,太大的接口將違背接口分離原則,靈活性較差,使用起來很不方便。
那這個度是如何控制的呢?這裏有一個準則是,基於客戶端須要的用途對功能進行分組,僅僅提供客戶端須要的行爲,不須要的行爲則隱藏起來,應當爲客戶端提供儘量小的單獨的接口,而不要提供大的總接口。
咱們能看出這是SRP的延伸,因此重構的過程當中,能夠結合接口隔離原則和單一職責原則進行代碼重構。
先說一下這個依賴關係是什麼。
在實際的開發過程當中,咱們不少人老是傾向於建立一些高層模塊依賴於低層模塊的開發策略,由於是低層次提供了對外的接口,高層次只能依賴於低層次所提供的接口,因此這個依賴關係應該是高層依賴於底層。
如何理解高層次和低層次?通俗點說:當A須要用到B時,那A就是高層次,B就是低層次。很明顯,若是設計了這些高層模塊依賴於低層模塊,那麼對低層模塊的改動就會直接影響到高層模塊,從而迫使它們須要做出改動,高層將沒有任何的自主性。
如何去除這樣的關係?依賴倒置原則提倡的是:高層模塊不該該依賴於低層模塊,至此咱們應該知道了這個倒置的含義,應該是解除高層和底層的直接耦合關係。很明顯,去除這層關係是對的,但如何實現呢?
依賴倒置的原則是:依賴抽象,不依賴具體實現,也就是高層和底層的耦合關係經過抽象(接口)來實現。這也是咱們提倡的面向接口編程,與之相關的概念是DI(依賴注入)和IoC(控制反轉)。
該原則規定了在類之間存在依賴關係的狀況下,應使用抽象(如接口)來構建它們的耦合關係,而不是直接引用類。 這減小了由低層次模塊的變化而致使高層模塊的改動。
一般咱們接手一個依賴關係很糟糕的項目要進行重構時,你會發現裏面代碼可能會混亂,脆弱且難以重用。在這過程當中咱們勢必要改變現有功能或添加新的功能,而這樣的代碼會讓咱們維護的過程變得舉步維艱。脆弱的代碼很容易形成bug的產生,常見的狀況是你一個區域的代碼發生變化時候,形成你其餘模塊出現bug。若是你聽從SOLID原則,那麼你能夠編寫出更靈活更健壯的代碼,而且具備更高的重用性。
設計模式就是實現了以上這些原則,從而達到了代碼複用、增長可維護性的目的。這些設計原則在編碼過程是很是有用的,它給予指導性的思想去編寫高質量的可重用代碼, 能夠顯著的提高咱們軟件的可維護性。
一般大部分的成熟重量級框架中,設計模式是必不可少的,相似於微軟的MVC,EntityFramework框架中,穿插着大量的設計模式,若是你熟悉了這些設計模式,毫無疑問,這將會助你迅速掌握框架的結構。
後面咱們將會針對上面提到的3人組設計模式進行實例講解,不必定全部的模式都會講到,由於在實際應用中,也不可能全部的設計模式都會用到,並且我的因爲工做經歷也沒徹底遇到和使用全部的設計模式:)
讓我知道若是你有更好的想法或建議:)