軟考架構師(9)——設計模式

全文連接:http://www.javashuo.com/article/p-ofmsztfa-gz.htmlhtml

設計模式深刻內容較多,我這裏只是列舉一些考試中的概念,若是你們想深刻理解一下能夠參考這個大佬的博客:https://www.cnblogs.com/zuoxiaolong/category/509144.htmljava

一:概述

概念:設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。算法

設計模式具備「適應需求變化」的優勢。shell

基本原則:模塊應對外擴展開放,而對修改關閉,要針對接口,而不是組合,抽象不該該依賴於細節,細節應當依賴於抽象數據庫

基本分類:共23種模式 3種分類 建立型5 結構型7 行爲型11編程

二:建立型5種 相公生原子

對象實例化的模式,建立型模式用於解耦對象的實例化過程。設計模式

抽象工廠模式(Abstract Factory Pattern) 

定義:(爲建立一組相關或相互依賴的對象提供一個接口,並且無須指定它們的具體類。)  安全

   所謂抽象工廠模式就是提供一個接口,用於建立相關或者依賴對象的家族,而不須要明確指定具體類。他容許客戶端使用抽象的接口來建立一組相關的產品,而不須要關係實際產出的具體產品是什麼。這樣一來,客戶就能夠從具體的產品中被解耦。它的優勢是隔離了具體類的生成,使得客戶端不須要知道什麼被建立了,而缺點就在於新增新的行爲會比較麻煩,由於當添加一個新的產品對象時,須要更加須要更改接口及其下全部子類。數據結構

工廠方法模式

定義:(定義一個用於建立對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類。)架構

  工廠方法模式很是符合「開閉原則」,當須要增長一個新的產品時,咱們只須要增長一個具體的產品類和與之對應的具體工廠便可,無須修改原有系統。同時在工廠方法模式中用戶只須要知道生產產品的具體工廠便可,無須關係產品的建立過程,甚至連具體的產品類名稱都不須要知道。雖然他很好的符合了「開閉原則」,可是因爲每新增一個新產品時就須要增長兩個類,這樣勢必會致使系統的複雜度增長。

 

生成器模式(Builder Pattern) 

定義:(將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。)

使用場景:

● 相同的方法,不一樣的執行順序,產生不一樣的事件結果時,能夠採用建造者模式。
● 多個部件或零件,均可以裝配到一個對象中,可是產生的運行結果又不相同時,則可使用該模式。
● 產品類很是複雜,或者產品類中的調用順序不一樣產生了不一樣的效能,這個時候使用建造者模式很是合適。
 
 

原型模式(Prototype Pattern)

定義:(用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。)

 

單子模式 (Singleton Pattern)

定義:(確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。)

使用場景:

● 要求生成惟一序列號的環境;
● 在整個項目中須要一個共享訪問點或共享數據,例如一個Web頁面上的計數器,能夠不用把每次刷新都記錄到數據庫中,使用單例模式保持計數器的值,並確保是線程安全的;
● 建立一個對象須要消耗的資源過多,如要訪問IO和數據庫等資源;
● 須要定義大量的靜態常量和靜態方法(如工具類)的環境,能夠採用單例模式(固然,也能夠直接聲明爲static的方式)。

  當系統中只須要一個實例對象或者系統中只容許一個公共訪問點,除了這個公共訪問點外,不能經過其餘訪問點訪問該實例時,可使用單例模式。

  單例模式的主要優勢就是節約系統資源、提升了系統效率,同時也可以嚴格控制客戶對它的訪問。也許就是由於系統中只有一個實例,這樣就致使了單例類的職責太重,違背了「單一職責原則」,同時也沒有抽象類,因此擴展起來有必定的困難。

 三:結構型7種 喬裝打扮想外住

 把類或對象結合在一塊兒造成一個更大的結構。

橋模式(Bridge Pattern)

定義:(將抽象和實現解耦,使得二者能夠獨立地變化。)

使用場景:

● 不但願或不適用使用繼承的場景
● 接口或抽象類不穩定的場景
● 重用性要求較高的場景
 
注意:

發現類的繼承有N層時,能夠考慮使用橋樑模式。橋樑模式主要考慮如何拆分抽象和實現。

 

裝飾(Decorator)模式

定義:(動態地給一個對象添加一些額外的職責。就增長功能來講,裝飾模式相比生成子類更爲靈活。)

使用場景:

● 須要擴展一個類的功能,或給一個類增長附加功能。
● 須要動態地給一個對象增長功能,這些功能能夠再動態地撤銷。
● 須要爲一批的兄弟類進行改裝或加裝功能,固然是首選裝飾模式。

 

代理模式(Proxy Pattern) 

定義:(爲其餘對象提供一種代理以控制對這個對象的訪問。)

 

適配器模式(Adapter Pattern)

定義:(將一個類的接口變換成客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做。)

使用場景:

你有動機修改一個已經投產中的接口時,適配器模式多是最適合你的模式。好比系統擴展了,須要使用一個已有或新創建的類,但這個類又不符合系統的接口,怎麼辦?使用適配器模式,這也是咱們例子中提到的。

注意事項:

詳細設計階段不要考慮使用適配器模式,使用主要場景爲擴展應用中。

 

享元模式(Flyweight Pattern)

定義:(使用共享對象可有效地支持大量的細粒度的對象。)

使用場景:

● 系統中存在大量的類似對象。
● 細粒度的對象都具有較接近的外部狀態,並且內部狀態與環境無關,也就是說對象沒有特定身份。
● 須要緩衝池的場景。

注意:

● 享元模式是線程不安全的,只有依靠經驗,在須要的地方考慮一下線程安全,在大部分場景下不用考慮。對象池中的享元對象儘可能多,多到足夠知足爲止。

● 性能安全:外部狀態最好以java的基本類型做爲標誌,如String,int,能夠提升效率。

 

外觀模式(Facade Pattern)

定義:(要求一個子系統的外部與其內部的通訊必須經過一個統一的對象進行。門面模式提供一個高層次的接口,使得子系統更易於使用。)

使用場景:

● 爲一個複雜的模塊或子系統提供一個供外界訪問的接口
● 子系統相對獨立——外界對子系統的訪問只要黑箱操做便可
● 預防低水平人員帶來的風險擴散
注意:
●一個子系統能夠有多個門面
●門面不參與子系統內的業務邏輯

 

 

組合(Composite)模式

定義:(將對象組合成樹形結構以表示「部分-總體」的層次結構,使得用戶對單個對象和組合對象的使用具備一致性。)

使用場景:

● 維護和展現部分-總體關係的場景,如樹形菜單、文件和文件夾管理。
● 從一個總體中可以獨立出部分模塊或功能的場景。

注意:

只要是樹形結構,就考慮使用組合模式。

 

四:行爲型11種 (訪問者經過觀察備忘錄模版狀態命令中介者迭代解釋職責策略)

類和對象如何交互,及劃分責任和算法。

訪問者模式(Visitor Pattern)

定義:(封裝一些做用於某種數據結構中的各元素的操做,它能夠在不改變數據結構的前提下定義做用於這些元素的新的操做。)

 

 

觀察者模式(Observer Pattern)

定義:(定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則全部依賴於它的對象都會獲得通知並被自動更新。)

使用場景:

● 關聯行爲場景。須要注意的是,關聯行爲是可拆分的,而不是「組合」關係。
● 事件多級觸發場景。
● 跨系統的消息交換場景,如消息隊列的處理機制。

注意:

● 廣播鏈的問題

在一個觀察者模式中最多出現一個對象既是觀察者也是被觀察者,也就是說消息最多轉發一次(傳遞兩次)。

● 異步處理問題

觀察者比較多,並且處理時間比較長,採用異步處理來考慮線程安全和隊列的問題。

 

 備忘錄模式(Memento Pattern)

定義:(在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣之後就可將該對象恢復到原先保存的狀態。)

使用場景:

● 須要保存和恢復數據的相關狀態場景。
● 提供一個可回滾(rollback)的操做。
● 須要監控的副本場景中。
● 數據庫鏈接的事務管理就是用的備忘錄模式。

注意:

●備忘錄的生命期

●備忘錄的性能

   不要在頻繁創建備份的場景中使用備忘錄模式(好比一個for循環中)。

 

 

模版模式(Template Method Pattern)

定義:(定義一個操做中的算法的框架,而將一些步驟延遲到子類中。使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。)

 

 

狀態模式

定義:(當一個對象內在狀態改變時容許其改變行爲,這個對象看起來像改變了其類。)

使用場景:

● 行爲隨狀態改變而改變的場景
這也是狀態模式的根本出發點,例如權限設計,人員的狀態不一樣即便執行相同的行爲結果也會不一樣,在這種狀況下須要考慮使用狀態模式。
● 條件、分支判斷語句的替代者

注意:

狀態模式適用於當某個對象在它的狀態發生改變時,它的行爲也隨着發生比較大的變化,也就是說在行爲受狀態約束的狀況下可使用狀態模式,並且使用時對象的狀態最好不要超過5個。

 

命令模式

定義:(將一個請求封裝成一個對象,從而讓你使用不一樣的請求把客戶端參數化,對請求排隊或者記錄請求日誌,能夠提供命令的撤銷和恢復功能。)

 

 

中介者(mediator)模式

定義:(用一箇中介對象封裝一系列的對象交互,中介者使各對象不須要顯示地相互做用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。)

使用場景:

中介者模式適用於多個對象之間緊密耦合的狀況,緊密耦合的標準是:在類圖中出現了蜘蛛網狀結構,即每一個類都與其餘的類有直接的聯繫。

 

 

迭代器模式(Iterator Pattern)

定義:(它提供一種方法訪問一個容器對象中各個元素,而又不需暴露該對象的內部細節。)

 

解釋器模式(Interpreter Pattern)

定義:(給定一門語言,定義它的文法的一種表示,並定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。)

使用場景:

● 重複發生的問題可使用解釋器模式

● 一個簡單語法須要解釋的場景

 

注意:

儘可能不要在重要的模塊中使用解釋器模式,不然維護會是一個很大的問題。在項目中可使用shell、JRuby、Groovy等腳本語言來代替解釋器模式,彌補Java編譯型語言的不足。

 

職責鏈模式

定義:(使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有對象處理它爲止。)

 

 

 

策略模式(Strategy Pattern)

定義:(定義一組算法,將每一個算法都封裝起來,而且使它們之間能夠互換。)

使用場景:

● 多個類只有在算法或行爲上稍有不一樣的場景。

● 算法須要自由切換的場景。

● 須要屏蔽算法規則的場景。

注意事項:具體策略數量超過4個,則須要考慮使用混合模式

 

最後 加上兩個 mvc 既是架構風格 也能夠是 設計模式
篩選器模式 java .net 在註冊訪問時 經常使用的方法
一、策略 二、觀察者、三、裝飾 四、工廠 五、單子 六、命令 七、適配器 8模版 九、組合 十、狀態
設計模式 是幹啥的 ? 是 對於一類問題的通用解決辦法
四要素 :模式名稱、問題、解決方案、效果

 

五:軟件設計原則

1.單一職責                                                                                                                                                     

一個類,只有一個引發它變化的緣由。應該只有一個職責。每個職責都是變化的一個軸線,若是一個類有一個以上的職責,這些職責就耦合在了一塊兒。這會致使脆弱的設計。當一個職責發生變化時,可能會影響其它的職責。另外,多個職責耦合在一塊兒,會影響複用性

簡單通俗的來講:一個類只負責一項職責。

 

遵循單一職責原的優勢有:

  • 能夠下降類的複雜度,一個類只負責一項職責,其邏輯確定要比負責多項職責簡單的多;

  • 提升類的可讀性,提升系統的可維護性;

  • 變動引發的風險下降,變動是必然的,若是單一職責原則遵照的好,當修改一個功能時,能夠顯著下降對其餘功能的影響。

須要說明的一點是單一職責原則不僅是面向對象編程思想所特有的,只要是模塊化的程序設計,都適用單一職責原則。

單一職責看似簡單,實際上在實際運用過程當中,會發現真的會出現不少職責擴展的現象,這個時候採用直接違反還會方法上遵循仍是徹底遵循單一職責原則仍是取決於當前業務開發的人員的技能水平和這個需求的時間,若是技能水平不足,確定會簡單的if else 去解決,不會想什麼原則,直接實現功能就行了,這也是爲何在不少小公司會發現代碼都是業務堆起來的,固然也有好的小公司代碼是寫的好的,這個也是不能否認的。不過無論採用什麼方式解決,心中至少要知道有幾種解決方法。

 

2.里氏替換原則 (Liskov Substitution Principle)                                                                       

里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 里氏代換原則中說,任何基類能夠出現的地方,子類必定能夠出現。 LSP是繼承複用的基石,只有當衍生類能夠替換掉基類,軟件單位的功能不受到影響時,基類才能真正被複用,而衍生類也可以在基類的基礎上增長新的行爲。里氏代換原則是對「開-閉」原則的補充。實現「開-閉」原則的關鍵步驟就是抽象化。而基類與子類的繼承關係就是抽象化的具體實現,因此里氏代換原則是對實現抽象化的具體步驟的規範。

 

 3.依賴倒置原則 (Dependence Inversion Principle)                                                       

所謂依賴倒置原則(Dependence Inversion Principle)就是要依賴於抽象,不要依賴於具體。實現開閉原則的關鍵是抽象化,而且從抽象化導出具體化實現,若是說開閉原則是面向對象設計的目標的話,那麼依賴倒轉原則就是面向對象設計的主要手段。

定義:高層模塊不該該依賴低層模塊,兩者都應該依賴其抽象;抽象不該該依賴細節;細節應該依賴抽象。

通俗點說:要求對抽象進行編程,不要對實現進行編程,這樣就下降了客戶與實現模塊間的耦合。

傳遞依賴關係有三種方式,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構造方法傳遞和setter方法傳遞,相信用過Spring框架的,對依賴的傳遞方式必定不會陌生。

在實際編程中,咱們通常須要作到以下3點:

  • 低層模塊儘可能都要有抽象類或接口,或者二者都有。【可能會被人用到的】

  • 變量的聲明類型儘可能是抽象類或接口。

  • 使用繼承時遵循里氏替換原則。

依賴倒置原則的核心就是要咱們面向接口編程,理解了面向接口編程,也就理解了依賴倒置。

 4.接口隔離原則 (Interface Segregation Principle)                                                                 

其原則字面的意思是:使用多個隔離的接口,比使用單個接口要好。本意下降類之間的耦合度,而設計模式就是一個軟件的設計思想,從大型軟件架構出發,爲了升級和維護方便。因此上文中屢次出現:下降依賴,下降耦合。

原定義:客戶端不該該依賴它不須要的接口;一個類對另外一個類的依賴應該創建在最小的接口上。 

接口隔離原則的含義是:創建單一接口,不要創建龐大臃腫的接口,儘可能細化接口,接口中的方法儘可能少。也就是說,咱們要爲各個類創建專用的接口,而不要試圖去創建一個很龐大的接口供全部依賴它的類去調用。本文例子中,將一個龐大的接口變動爲3個專用的接口所採用的就是接口隔離原則。在程序設計中,依賴幾個專用的接口要比依賴一個綜合的接口更靈活。接口是設計時對外部設定的「契約」,經過分散定義多個接口,能夠預防外來變動的擴散,提升系統的靈活性和可維護性。

說到這裏,不少人會覺的接口隔離原則跟以前的單一職責原則很類似,其實否則。其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。其二,單一職責原則主要是約束類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口接口,主要針對抽象,針對程序總體框架的構建。

採用接口隔離原則對接口進行約束時,要注意如下幾點:

  • 接口儘可能小,可是要有限度。對接口進行細化能夠提升程序設計靈活性是不掙的事實,可是若是太小,則會形成接口數量過多,使設計複雜化。因此必定要適度。

  • 爲依賴接口的類定製服務,只暴露給調用的類它須要的方法,它不須要的方法則隱藏起來。只有專一地爲一個模塊提供定製服務,才能創建最小的依賴關係。

  • 提升內聚,減小對外交互。使接口用最少的方法去完成最多的事情。

運用接口隔離原則,必定要適度,接口設計的過大或太小都很差。設計接口的時候,只有多花些時間去思考和籌劃,才能準確地實踐這一原則。

 

5.迪米特法則(最少知道原則) (Demeter Principle)                                                                                  

爲何叫最少知道原則,就是說:一個實體應當儘可能少的與其餘實體之間發生相互做用,使得系統功能模塊相對獨立。也就是說一個軟件實體應當儘量少的與其餘實體發生相互做用。這樣,當一個模塊修改時,就會盡可能少的影響其餘的模塊,擴展會相對容易,這是對軟件實體之間通訊的限制,它要求限制軟件實體之間通訊的寬度和深度。

定義:一個對象應該對其餘對象保持最少的瞭解。

迪米特法則的初衷是下降類之間的耦合,因爲每一個類都減小了沒必要要的依賴,所以的確能夠下降耦合關係。可是凡事都有度,雖然能夠避免與非直接的類通訊,可是要通訊,必然會經過一個「中介」來發生聯繫,例如本例中,總公司就是經過分公司這個「中介」來與分公司的員工發生聯繫的。過度的使用迪米特原則,會產生大量這樣的中介和傳遞類,致使系統複雜度變大。因此在採用迪米特法則時要反覆權衡,既作到結構清晰,又要高內聚低耦合。

6.開閉原則(Open Close Principle)                                                                                               

開閉原則就是說對擴展開放,對修改關閉。在程序須要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。因此一句話歸納就是:爲了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,須要面向接口編程。

定義:一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉

相關文章
相關標籤/搜索