設計模式小結

開始的毛病:變量命名不規範,if-else判斷有的代碼做無用功,代碼健壯性太差,沒有做try-cath異常處理

工廠模式(創建型模式):

創建對象接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建延伸到子類進行
主要解決接口選擇問題,明確計劃不同條件下執行創建不同實例
通過子類實現工廠實例,創建過程在其子類執行
優點:提高擴展性,屏蔽產品具體實現,調用者只關心產品接口; 缺點:增加一個產品,會導致系統中類個數增加,造成系統複雜度
使用場景:
1.日誌記錄:用戶選擇將日誌記錄到磁盤/系統事件/遠程服務器
2.數據庫訪問:系統採用不同的數據庫
3.設計連接服務器的框架, 比如針對pop3, imap, http設計接口
注:工廠模式作爲類的創建模式, 複雜的對象使用工廠模式, 簡單對象使用new, 而非工廠模式
簡單工廠:一個工廠類,一個產品抽象類
工廠方法:多個工廠類,一個產品抽象類
抽象工廠:多個工廠類,多個產品抽象類

採用鬆耦合,多態的方式,使得我想要哪一個功能,就生成相應對象, 問題的考慮方向只需放在要實例化哪個類,要增加哪一項功能
也可以使用枚舉的方式, 實現工廠模式: 將每個工廠實例作爲枚舉對象,通過枚舉工廠進行調用

抽象工廠模式(創建型模式,其他工廠的工廠):

接口只負責創建一個相關的對象的工廠,不需要顯式指定類,工廠模式就能按照工廠模式提供對象(多態)
用於解決接口選擇問題
優點:當產品族中,多個對象被設計成一起工作,能保證客戶端只使用一個產品族中對象
缺點:產品族中擴展產品,需要在抽象類中添加代碼, 還需要在具體實現裏面添加代碼
懂得一點,使用設計模式, 先搞定UML
建立多個工廠, 然後建立一個總的工廠,通過總的工廠調用下屬,主要還是多態的性質運用, 程序中還有很多瑕疵
主要還是接口的選擇, 以及狀態的變化

單例模式(創建型模式):

涉及到的單一的類,該類只負責自己對象的創建,並且只有單個對象被創建,提供唯一的對象訪問方式,可直接訪問
注: 只能有一個實例作爲全局的訪問點, 構造函數私有,單例類只能自己創建自己唯一的實例, 必須給所有其他對象提供這一實例;

!!!使用synchronized防止多線程同時創建多個實例

主要用於:控制資源,全局使用的類創建/銷燬
優點:只有一個實例,減少資源開銷,避免對資源的多重佔用(寫文件操作)
缺點:沒有接口,不能被繼承,只關心內部邏輯,不關心外部
使用場景–產品的唯一序列號; web計數器,使用單例將其緩存,不用每次在數據庫中刷新; 創建對象消耗資源, 比如IO,數據庫連接
懶漢模式/餓漢模式—在/不在類內方法構造實例

建造者模式(創建型模式,使用多個簡單對象構建複雜對象):

使用: 基本組件不變,其組合常常在變化, 將變的部分和不變的部分分開
建造者:創建和提供實例, 導演: 管理建造出來的實例的依賴關係
優點:建造者獨立,易擴展; 便於控制細節風險
缺點: 產品必須有公共點,範圍有限制; 生成對象之間有依賴關係
注: 建造者模式與工廠模式的區別—建造者更關注零件的裝配順序, 將一個複雜的構建過程與其表示相分離, 並不是由建造者負責一切,而是由監工負責控制(定義)一個複雜的構建過程,由各個不同的建造者分別實現構建過程所用到的構建步驟

原型模式(創建型模式,創建重複對象且保證性能):

該模式創建一個原型接口,此接口用於創建對象的克隆. 例:將一些高代價的對象進行緩存,在下一次請求創建的時候返回他的克隆, 減少資源開銷
優點: 性能提高,逃避構造函數的約束
缺點:配備克隆操作需要對類的功能全盤考慮,對已有的類不一定很容易,特別是當一個類飲用不支持串行化的間接對象,或者引用含有循環結構; 必須實現Cloneable接口
什麼時候使用–一個系統應該獨立立於它的產品創建,構成,表示; 實例化的類是在運行時指定,如動態裝載; 爲了避免創建一個和產品類層次平行的工廠類層次時; 當一個類的實例只能有幾個不同狀態組合中的一種時,
使用場景–
1.資源優化, 類加載需要消耗很多資源, 性能和安全要求高的場景
2.通過new產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模型
3.一個對象,多個修改者
4.大多數眼型模式伴隨工廠模式出現,通過clone方法創建一個對象,然後由工廠方法提供給調用者
注:原型模式通過拷貝一個現有對象生成新對象, 淺拷貝實現Clonable接口, 重寫clone方法, 深拷貝通過實現Serializable讀取二進制流
//////
原型角色:定義用於複製現有的實例來生成新的實例的方法(實現Cloneable接口的類)
具體原型角色:實現用於複製現有實例來生成新實例的方法(具有clone()方法的類)
使用者角色:維護一個註冊表, 提供獲取clone的類

適配器模式(結構型模式):

是作爲兩個不兼容的接口之間的橋樑,結合兩個獨立的接口; 這種模式涉及到一個單一的類, 該類負責加入獨立的或不兼容的接口的功能; 例如讀卡器連接內存卡與筆記本
實現方式: 一般通過適配器繼承或者以來已有對象, 實現想要的目標接口
優點: 可以讓兩個沒有關係的接口/類一起運行, 提高類的複用性, 增加類的靈活性
缺點:
過多使用適配器造成系統凌亂, 例如:表面上使用A接口,適配器卻將A改爲B接口,造成接口使用的混亂, 因此如果不是有必要的, 可以不使用適配器, 而是直接對系統重構
由於java單繼承, 當適配類的時候, 只能適配一個類(爲抽象類);
注: 適配器主要是用與解決正在服役的項目的問題, 不是在類詳細設計的時候添加

橋接模式(結構型模式):

抽象類依賴實現類,用於把抽象化與實現化解耦,使二者可以獨立變化, 提供抽象化和實現化直接的橋接結構; 使得實體類的功能能獨立於接口實現類
主要解決類繼承造成的爆炸問題,應對類的多種變化, 便與擴展; 實現系統多個角度分類,每一個角度都可能會變化
優點:抽象與實現的分離, 優秀的擴展功能, 實現細節對客戶透明
缺點: 增加系統設計理解難度,由於聚合關係建立在抽象層,要求針對抽象進行設計與編程
使用場景:

  1. 系統需要在構建的抽象化角色和具體角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承關係, 通過橋接模式使得他們在抽象層建立一個關聯關係
  2. 避免因繼承,或多層次繼承導致系統類的個數急劇增加2.避免因繼承,或多層次繼承導致系統類的個數急劇增
  3. 一個類存在兩個獨立變化的維度, 且兩個維度需要進行擴展3.一個類存在兩個獨立變化的維度, 且兩個維度需要進行擴展

類的功能層次結構:父類具有基本功能,子類增加新的功能類的功能層次結構:父類具有基本功能,子類增加新的功能
類的實現層次結構:父類通過聲明抽象方法定義接口,子類通過實現具體的方法來實現接口
橋接模式的角色:
抽象化角色:實現者角色提供的接口來定義基本功能接口,持有實現者角色,並在功能中委託給他,起到搭建橋樑的作用, 抽象化角色非抽象類,而指抽象了實現
改善後的抽象化角色:作爲抽象化角色的子類,增加新功能,增加新的接口,與其構成類的功能層次結構
實現者角色:提供用於抽象化角色的接口,它是一個抽象類/接口
具體實現者角色:作爲實現者角色的子類,通過實現具體方法來實現接口,與其構成類的實現層次結構

過濾器/標準模式(結構型模式):

通過不同的標準來過濾一組對象,通過邏輯運算符以解耦的方式把他們連接起來
在java8中,最典型的應用就是分組操作,根據指定的指標進行分組篩選(如Collectors.groupingBy(Persons::getGender)分組條件爲getGender)

組合/整體模式(結構型模式):

就是在一個對象中包含其他對象,這些被包含的對象可能是終點對象(不再包含別的對象),也有可能是非終點對象(其內部還包含其他對象,或叫組對象),
我們將對象稱爲節點,即一個根節點包含許多子節點,這些子節點有的不再包含子節點,而有的仍然包含子節點,以此類推。
通過組合的方式(在對象內部引用對象)來進行佈局,我認爲這種組合是區別於繼承的,而另一層含義是指樹形結構子節點的抽象(將葉子節點與數枝節點抽象爲子節點),區別於普通的分別定義葉子節點與數枝節點的方式。
主要解決:在樹型結構的問題中,模糊了簡單元素和複雜元素的概念, 客戶程序處理複雜元素如同簡單元素,使客戶程序與複雜元素的內部結構解耦;表示對象的部分-整體層次結構, 用戶忽略組合對象與單個對象的不同,用戶統一使用組合結構中的所有對象
優點:高層模塊調用簡單,節點自由增加
缺點:由於葉子和樹枝聲明爲實現類,而非接口, 違反依賴倒置原則
注: 通常樹枝內部組合接口, 含有List,裏面具有Component

裝飾器模式(結構型模式):

允許向一個現有的對象添加新的功能,同時不改變其結構(作爲現有類的一個包裝);
動態爲對象添加一些額外的職責,就增加功能來說,裝飾模式相比生成子類更加靈活;
一般情況,爲擴展一個類經常使用繼承,相反,子類會變得很膨脹, 應該將具體功能劃分,同時繼承裝飾者模式
優點:裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式就是繼承的一個替代模式,可以動態擴展一個實現類的功能
缺點:多層裝飾比較複雜

外觀模式(結構型模式):

向客戶端提供一個客戶端可以訪問的系統接口, 類似於中介模式,隱藏系統的複雜性;只涉及到一個單一的類;
爲子系統中一組接口提供一個一致的界面,外觀模式定義一個高層接口,使得子系統更加容易使用;
此模式用於降低訪問複雜系統的內部子系統的複雜度,簡化客戶端與之的接口
注:在客戶端和複雜系統之間再加一層,這一層將調用順序,依賴關係處理好
優點:減少系統相互依賴, 提高靈活性, 提高安全性
缺點:不符合開閉原則,改寫代碼很麻煩,繼承重寫不適合
使用場景:爲複雜系統的模塊或子系統提供外界訪問的模塊;子系統相對獨立;

享元模式(結構型設計模式):

用於減少創建對象的數量,以減少內存佔用和提高性能;嘗試重用現有的同類對象,未找到匹配對象,則創建新對象;運用共享技術有效地支持大量細粒度的對象, 類似於單例模式
主要解決: 有大量對象時,可能造成內存溢出,把共同部分抽象出來,如果有相同的業務請求,直接返回在內存中已有的對象,避免重新創建; 一般使用HashMap存儲這些對象
優點:大大減少對象的創建,降低系統的內存
缺點:提高系統的複雜度,需要分離出外部狀態,內部狀態;外部狀態具有固有化的性質,不應該隨內部狀態的變化而變化
注:注意劃分外部狀體和內部狀態,否則會引起線程安全問題; 這些類必須有一個工廠對象加以控制
該模式優點相似單例模式,都是爲了避免創建過多相似對象浪費空間內存資源

代理模式(結構型模式):

一個類代表另一類的功能,爲其他對象提
供一種代理以控制對這個對象的訪問(即代理權),使用在想訪問一個類時做一些控制
一般添加中間層解決代理問題
,比如:複製粘貼的快捷方式
注:
1.與適配器模式的區別: 適配器主要是考慮改變對象的接口,而代理模式不能改變所代理類的接口
2.與裝飾器模式的區別: 裝飾器模式是爲了增強功能, 代理模式是爲了加以控制
JDK自帶動態代理—java.lang.reflect.Proxy生成動態代理類和對象; java.lang.reflect.InvocationHandler可以通過invoke方法實現對真實角色的代理訪問

責任鏈模式(行爲模式):

爲請求創建一個接受這對象的鏈,對請求的發送者和接受者進行解耦,通常每個接受者都包含另一個接受者的引用,如果一個對象不能處理該請求,他會把相同的請求傳遞給下一個接受者,直到找到符合處理當前任務的對象
避免請求者與接受者耦合,讓多個對象都有可能接受請求,將對象連接成一條鏈,沿着這一條鏈傳遞請求,直到有對象處理它爲止
注:Handler裏面聚合他自己,在HanleRequest裏面判斷是否合適,如果沒有達到條件則向下傳遞,向誰傳遞之前set進去; JavaWeb中遇到很多應用
優點:減低耦合度,將請求者和接受者解耦,簡化對象,使對象不需要知道鏈的結構, 增強給對象指派職責的靈活性,通過改變鏈內的成員或者調動他們的次序,允許動態的增加或刪除責任,增加新的請求方便
缺點:不能保證請求一定被接收, 系統性能會受到一定影響,在進行代碼調試時不方便,會造成循環調用, 不容易觀察運行時特徵
使用場景–多個對象處理同一個請求,具體處理該請求由運行時刻確定; 在不確定指定接受者的情況下, 向多個對象中提交一個請求; 動態指定一組對象處理請求

命令模式(行爲模式):

數據驅動型設計模式,請求以命令的形式包裹在對象中,並傳給對象,調用對象尋找可以處理該命令的合適對象,並把該命令傳給相應的對象,此對象執行命令
主要解決行爲請求者與實現者之間的鬆耦合,一般情況行爲請求者與實現者是緊耦合關係, 在針對記錄的撤銷重做,事務處理就必須保證鬆耦合
關鍵代碼: 定義三個角色: 1.received真正的命令執行對象, 2.Command 3.invoker使用命令對象的入口
優點: 降低系統耦合度, 新的命令可以添加到系統中去
缺點:導致系統有過多的具體命令類
使用場景:例:GUI中的按鈕, 模擬CMD, 腳本編程

解釋器模式(行爲模式):

實現一個表達式接口,解釋一個特定的上下文,多用於SQL解釋,符號處理引擎,主要是還是固定文法的解釋
通常構建語法樹,定義終結符,非終結符, 構建環境多采用HashMap
該模式使用場景少,對於複雜文法難以維護,引起類膨脹,且解釋器通常使用遞歸調用方法,Java中多采用experssion4J代替

迭代器模式(行爲模式):

主要用於順序訪問迭代器中元素,典型的Java中的Iterator
注:迭代器分離了集合對象的遍歷行爲,做到不暴露集合內部結構,且讓外部代碼做到透明地訪問集合內部的元素

中介模式(行爲模式):

降低多個對象與類之間的通信複雜, 此模式提供一箇中介類, 該類通常處理不同類之間的通信, 並支持鬆耦合, 使代碼便於維護
使用中介對象封裝一系列對象之間的交互方式, 中介者使個對象不需要顯式的互相引用, 主要解決對象與對象之間的大量耦合關係
使用場景: 系統中對象之間存在較爲複雜的引用關係, 導致他們之間的依賴關係複雜而難以複用該對象; 通過一箇中間類封裝多個類中的行爲, 而又不想生成太多子類
注: 不應當在職責混亂的時候使用

備忘錄模式(行爲模式):

在不破壞封裝性的前提下,捕獲一個對象的內部狀態,保存一個對象的某個狀態, 在合適的情況下恢復此對象; 例如Ctr+Z
注:整個過程一般增加一個備忘錄類, 爲節約內存,通常使用原型模式+備忘錄模式

觀察者模式(行爲模式):

當對象存在一對多的關係的時候,觀察者將一個對象的修改情況自動通知其他的依賴他的對象;廣播通知;觸發機制鏈
一般在抽象類中使用ArrayList存放觀察者

優點:觀察者與被觀察者抽象耦合
缺點:當一個被觀察對象存在多個觀察者,通知所有觀察者將會花費較多的時間, 若觀察者與被觀察者之間存在循環關係,可能會導致死循環通知;觀察者模式通知觀察者觀察目標發生了變化,並沒有告訴觀察者目標對象是怎樣發生變化的
注:java中存在對觀察者支持的類, 避免循環引用; 當一個觀察者出現錯誤的時候將會導致系統錯誤,一般採用異步的方式

狀態模式(行爲模式):

允許對象在內部狀態發生改變的時改變他的行爲, 對象看起來修改了他的類, 主要解決對象的行爲依賴於他的狀態,並根據他的狀態改變而改變他的相關行爲, 類似於廣播通知
通常將具體的狀態抽象出來
優點:封裝轉換原則;枚舉所有的狀態;可讓多個環境對象共享一個狀態對象,從而減少系統中對象的個數
缺點:使用不當將會導致系統結構混亂, 不太支持開閉原則, 切換狀態將會修改負責狀態轉換的代碼
注:在行爲狀態受約束的時候使用狀態模式,且狀態不超過5個

空對象模式:

使用空對象取代null, 取代的過程中並不是對象不存在,而是面對反應的時候不作出任何動作

模板方法設計模式(行爲模式):

定義操作中算法的骨架,將通用的算法抽象出來, 抽象類定義算法的方式/模板, 子類按需要重寫
優點: 封裝不變的部分,擴展變的部分, 行爲由父類控制, 子類實現
缺點:每種不同的實現都需要子類去實現, 導致類的個數增加
注:爲防止惡意操作, 將模板方法加上final關鍵字
爺爺(接口)->父親(抽象類)->兒子(最終實現類); 兒子重寫父類方法, 父類重寫爺爺方法, 進行方法查找只能去爺爺輩查找,多態的原因去父類中查找, 但是子類重寫父類方法, 最終去子類中查找

訪問者模式(行爲模式):

將數據結構與數據操作分離,解決穩定的數據結構與易變的操作之間的耦合,避免對象的操作污染對象的類, 訪問者將訪問過程的操作封裝到類中
在訪問的類裏面加一個對外提供接待訪問者的接口
優點: 符合單一職責, 良好擴展性,靈活性
缺點:具體元素對訪問者公佈細節

MVC模式(模式-視圖-控制器):

用於應用程序的分層開發
model:代表一個存取數據的對象; view:數據的可視化 controller:控制數據流向模型對象,更新視圖,將視圖與模型分離開
業務代表模式: 對表示層和業務層解耦, 減少通信或對表示層代碼中的業務層代碼的遠程查詢功能
客戶端 client: jsp, Servlet, UIJava,選擇業務代表
業務代表 BusinessDelegate: 提供對業務服務方法的訪問,選擇服務
查詢服務: 獲取相關業務實現, 提供對象對業務代表對象的訪問
業務服務: 業務接口,實現業務服務的實體類, 提供實際業務實現邏輯
//將業務訪問的服務與用戶所需要的服務通過業務代表選擇對應的服務

組合體模式:

用在EJB持久化機制中; 一個組合實體是一個EJB實體bean, 代表對象的圖解; 當更新一個組合實體時, 內部依賴對象beans會自動更新
組合實體(Composite Entity):主要實體bean, 可以是粗粒的, 或者包含一個粗粒對象, 用於持續生命週期
粗粒度對象(Coarse-Grained Object):此對象包含依賴對象, 具有自己的生命期, 也能管理依賴對象的生命期
依賴對象(Dependent Object): 是一個持續生命期依賴於粗粒度對象的對象
策略(Strategies): 如何實現組合實體
整個過程中層層解耦, 由小到大由底層到上層, 最終的底層實現由依賴對象實現有點像工廠模式/策略模式(負責處理組合體)

數據訪問對象模式:

就是將JDBC從高級業務中抽取出來, 不去幹擾業務操作
數據對象訪問接口(Data Access Object Interface): 定義模型對象執行的標準操作
數據訪問對象實體類(Data Access Object concrete class): 實現上述接口
模型對象/數值對象(Model Object/Value Object): get/set方法檢索數據

前端控制器模式:

提供一個集中的請求處理機制, 將所有請求交給單一的處理程序(認證,授權,記錄日誌,跟蹤請求)
前端控制器(Front Controller):基於Web應用程序, 基於桌面應用程序
調度器(Dispatcher):使用一個調度對象來調度請求到相應的具體處理程序
視圖(view)
與組合模式差不多

攔截器模式:

對程序的請求或響應做出預處理/後處理, 與過濾模式,責任鏈模式雷同
過濾器(Filter):過濾器在請求之前/之後,執行某些任務
過濾器鏈(Filter Chain):具有多個過濾器,順序執行
Target: 目標對象,交由過濾器處理
過濾管理器(Filter Manger):管理過濾器/過濾鏈
Client:向target發送請求對象

服務期定位模式:

利用緩存技術, 類似於單例模式/原型模式, 避免重複new 服務對象, 造成資源浪費
服務(Service):實際處理請求服務
Context: 帶有對要查找對象的引用
緩存(Cache):緩存儲存服務的引用,以便重複使用
Client: ServiceLocator調用服務對象

傳輸對象模式:

用於從客戶端向服務端傳輸帶有多個屬性的數據(帶有get/set方法的POJO類 或者 序列化對象,類)
業務對象(Business Object):爲傳輸對象填充的數據
傳輸對象(Transfer Object):簡單POJO,只有設置/獲取屬性的方法
客戶端(Client):接收傳送對象

業務的封裝:

讓業務邏輯和界面邏輯分開,降低耦合度,使之達到可擴展,可維護
例: 將測試代碼, 功能實現代碼分開
緊耦合,鬆耦合
緊耦合:當一個類中含有多個功能,例如Collections,當我修改sort函數, 或者添加功能有可能將其他功能改變,或者對其他功能造成影響,耦合度過高
鬆耦合:
將類中各個功能抽象出單獨的類, 然後每個類又去實現最初的Collections接口,或者繼承Collections,將各個功能模塊分開,使得功能之間互不影響,就此保證良好的可擴充性
在鬆耦合的前提下,需要考慮哪些功能需要單獨抽象爲類,哪些不需要, 不能做沒有意義的抽象,說明----面向對象的編程,不是類越多越好, 類的劃分只是爲了封裝, 分類的基礎是抽象, 具有相同和功能的抽象集合纔是類

策略模式(行爲模式):

一個類的行爲或算法在運行過程中修改,在相同條件下避免if-else帶來的複雜性,以及難以維護,實現同一個接口讓算法之間可以做到相互替換
優點:算法自由切換, 擴展性好, 避免多重if-else判斷
缺點:策略類增多, 所有策略類需要對外暴露
以相同的方式調用所有的算法,減少各種算法類與使用算法類之間的耦合;還是封裝"規則"
基本的策略模式: 具體的策略選擇由客戶端對象選擇嗎並沒有解除客戶端選擇判斷的壓力,使用工廠模式與策略模式結合,將判斷過程轉移到工廠模式中

單一原則:

一個類中,應該僅有一個引起它變化的原因
一個類承擔的職責過多,造成職責耦合,當一個職責變化將會導致其他功能受到影響, 解決方式:將界面與代碼邏輯分開

開放封閉原則:

對於擴展是開放的,對於更改是封閉的,面對需求,對程序的改動只用於增加新的代碼,而不是改變現有的代碼
例:對共同存在的功能抽象爲類, 增加功能的時候只需要添加實現類

依賴倒轉原則:

高層模型不能依賴低層模型, 兩個應該依賴接口; 例如:高層依賴低層, 當複用高層的時候, 就需要改變低層, 造成大量代碼改動
抽象不應該依賴細節,細節應該依賴抽象

里氏代換原則:

子類型必須能夠替換他們的父類型, 例:鳥類,企鵝類,企鵝類不能繼承鳥類(企鵝不會飛),若繼承鳥類,造成飛的屬性不能被複用
注:此原則保證繼承複用成爲可能,只有當子類可以替換父類,軟件的功能單位不受影響,父類才能被真正重用,
子類也可在父類的基礎上擴展新的功能
總述:針對抽象編程, 依賴關係都是依賴於抽象類或接口
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章