GOF设计模式(概念、原则、场景、优点、缺点、应用)
設計模式是軟件大師們根據多年來的軟件開發經驗,對軟件開發領域包括合理復用、提高健壯性、減少BUG等各方面作的抽象總結,不同的設計模式方法適合于不同的應用場景,是匯結了他們最寶貴的經驗總結。最早的開發模式是1994年GOF四人共同完成的《Design Patterns - Elements of Reusable Object-Oriented Software》一書提及的23種經典設計模式,至今仍是設計模式方面,經典中的經典著作。
?
一、設計模式的六大原則:
總原則-開閉原則
對擴展開放,對修改封閉。在程序需要進行拓展的時候,不能去修改原有的代碼,而是要擴展原有代碼,實現一個熱插拔的效果。所以一句話概括就是:為了使程序的擴展性好,易于維護和升級。
想要達到這樣的效果,我們需要使用接口和抽象類等,后面的具體設計中我們會提到這點。
1、單一職責原則
不要存在多于一個導致類變更的原因,也就是說每個類應該實現單一的職責,否則就應該把類拆分。
2、里氏替換原則(Liskov Substitution Principle)
任何基類可以出現的地方,子類一定可以出現。里氏替換原則是繼承復用的基石,只有當衍生類可以替換基類,軟件單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為。
里氏代換原則是對“開-閉”原則的補充。實現“開閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。里氏替換原則中,子類對父類的方法盡量不要重寫和重載。因為父類代表了定義好的結構,通過這個規范的接口與外界交互,子類不應該隨便破壞它。
3、依賴倒轉原則(Dependence Inversion Principle)
面向接口編程,依賴于抽象而不依賴于具體。寫代碼時用到具體類時,不與具體類交互,而與具體類的上層接口交互。
4、接口隔離原則(Interface Segregation Principle)
每個接口中不存在子類用不到卻必須實現的方法,如果不然,就要將接口拆分。使用多個隔離的接口,比使用單個接口(多個接口方法集合到一個的接口)要好。
5、迪米特法則(最少知道原則)(Demeter Principle)
一個類對自己依賴的類知道的越少越好。無論被依賴的類多么復雜,都應該將邏輯封裝在方法的內部,通過public方法提供給外部。這樣當被依賴的類變化時,才能最小的影響該類。
最少知道原則的另一個表達方式是:只與直接的朋友通信。類之間只要有耦合關系,就叫朋友關系。耦合分為依賴、關聯、聚合、組合等。我們稱出現為成員變量、方法參數、方法返回值中的類為直接朋友。局部變量、臨時變量則不是直接的朋友。我們要求陌生的類不要作為局部變量出現在類中。
6、合成復用原則(Composite Reuse Principle)
盡量首先使用合成/聚合的方式,而不是使用繼承,即組合優于繼承.
?
按照類型,可分為3類:
1、創建型模式:抽象工廠、建造者模式、工廠方法、原型模式、單例模式;
創建型模式抽象了實例化的過程。創建性模式隱藏了這些類的實例是如何被創建和放在一起,整個系統關于這些對象所知道的是由抽象類所定義的接口。這樣,創建性模式在創建了什么、誰創建它、她是怎么被創建的、以及何時創建方面提供了靈活性。創建相應數目的原型并克隆她們通常比每次用適合的狀態手工實例化該類更方便。
2、結構型模式:適配器模式、橋接模式、組合模式、裝飾者模式、外觀模式、享元模式、代理模式;
3、行為型模式:觀察者模式、模板方法、命令模式、狀態模式、職責鏈模式、解釋器模式、中介者模式、訪問者模式、策略模式、備忘錄模式、迭代器模式。
4、MVC模式:集觀察者、組合、策略為一體,是多種模式的綜合應用,算是一種架構模式。
?
下面按照【概念】+【原則】+【場景】+【優點】+【缺點】+【應用】分別簡述一下24種設計模式:
?
1、抽象工廠模式(Abstract Factory)
提供一個創建一系列相關或互相依賴對象的接口,而無需指定它們具體的類。
原則:
?? ?LSP 里氏替換原則
場景:
?? ?創建不同的產品對象,客戶端應使用不同的具體工廠。
優點:
?? ?1、改變具體工廠即可使用不同的產品配置,使改變一個應用的具體工廠變得很容易。
?? ?2、讓具體的創建實例過程與客戶端分離,客戶端通過抽象接口操作實例,產品的具體類名也被具體工廠的實現分離。
缺點:
?? ?如果要新增方法,改動極大。
應用:
?? ?1、jdk中連接數據庫的代碼是典型的抽象工廠模式,每一種數據庫只需提供一個統一的接口:Driver(工廠類),并實現其中的方法即可。不管是jdbc還是odbc都能夠通過擴展產品線來達到連接自身數據庫的方法。
?? ?2、java.util.Collection 接口中定義了一個抽象的 iterator() 方法,該方法就是一個工廠方法。對于 iterator() 方法來說 Collection 就是一個抽象工廠。
?
2、建造者模式(Builder)【又名,生成器模式】
將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
原則:
?? ?依賴倒轉原則
場景:
?? ?如果需要將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建造者模式是當創建復雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時適用的模式。
優點:
?? ?使得建造代碼與表示代碼分離。
缺點:
?? ?1、增加代碼量;
?? ?2、Builder只是一個替代構造器的選擇,不能直接用于降低非構造函數方法的參數數量。
應用:
?? ?StringBuilder和StringBuffer的append()方法
?
3、工廠方法模式(Factory Method)
定義一個用于創建對象的接口,讓子類決定實例化哪一個類,工廠方法使一個類的實例化延遲到其子類。
原則:
?? ?開放封閉原則
場景:
?? ?不改變工廠和產品體系,只是要擴展產品(變化)。
優點:
?? ?是簡單工廠模式的進一步抽象和推廣,既保持了簡單工廠模式的優點(工廠類中包含了必要的邏輯判斷,根據客戶端的選擇條件動態實例化相關的類。對于客戶端來說,去除了與具體產品的依賴),而且克服了簡單工廠的缺點(違背了開放封閉原則)。
缺點:
?? ?每增加一個產品,就需要增加一個產品工廠的類,增加了額外的開發。(用反射可以解決)。
應用:
?? ?1、Collection中的iterator方法;
?? ?2、java.lang.Proxy#newProxyInstance()
?? ?3、java.lang.Object#toString()
?? ?4、java.lang.Class#newInstance()
?? ?5、java.lang.reflect.Array#newInstance()
?? ?6、java.lang.reflect.Constructor#newInstance()
?? ?7、java.lang.Boolean#valueOf(String)
?? ?8、java.lang.Class#forName()
?
4、原型模式(prototype):【又名,生成器模式】
用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。
原則:
場景:
?? ?在初始化信息不發生變化的情況,用克隆進行拷貝。
優點:
?? ?隱藏了對象創建的細節,大大提升了性能。不用重新初始化對象,而是動態的獲得對象運行時的狀態。
缺點:
?? ?深復制 or 淺復制 。
應用:
?? ?JDK中的Date類。
?
5、單例模式(Singleton)
保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
原則:
?? ?封裝
場景:
?? ?通常,我們可以讓一個全局變量使得一個對象被訪問,但它不能防止你實例化多個對象,一個最好的辦法就是,讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例可以被創建,而且它可以提供一個訪問該實例的方法。
優點:
?? ?對唯一實例的受控訪問。
缺點:
?? ?餓漢式/懶漢式??多線程同時訪問時可能造成多個實例。
應用:
?? ?1、java.lang.Runtime; GUI中也有一些(java.awt.Toolkit#getDefaultToolkit()?java.awt.Desktop#getDesktop())
?
6、適配器模式(Adapter)
將一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。在GoF的設計模式中,適配器有兩種類型,類適配器模式和對象適配器模式。
?? ?1、類適配器模式:通過多重繼承對一個接口與另一個接口進行匹配,而C#,Java等語言都不支持多重繼承,也就是一個類只有一個父類。
?? ?2、Java一般都指的是 對象適配器模式
場景:
?? ?適配器是為了復用一些現有的類。系統的數據和行為都正確,但是接口不符,這時采用適配器模式,使原有對象和新接口匹配。
優點:
?? ?能夠復用現存的類,客戶端統一調用同一接口,更簡單、直接、緊湊。
缺點:
?? ?適配器模式有點兒“亡羊補牢”的感覺,設計階段要避免使用。
應用:
?? ?在Java jdk中,適配器模式使用場景很多,如
?? ?集合包中Java.util.Arrays#asList()、
?? ?IO包中java.io.InputStreamReader(InputStream)、java.io.OutputStreamWriter(OutputStream) 等
?
7、橋接模式(Bridge)
將抽象部分與它的實現部分分離,使它們都可以獨立的變化。
原則:
?? ?合成/聚合復用原則
場景:
?? ?實現系統可能有多角度分類,每一種分類都有可能變化,那么就把這種多角度分離出來讓它們獨立變化,減少它們之間的耦合。
優點:
?? ?減少各部分的耦合。 分離抽象和實現部分,更好的擴展性,可動態地切換實現、可減少子類的個數。
缺點:
?? ?1、橋接模式的引入會增加系統的理解與設計難度,由于聚合關聯關系建立在抽象層,要求開發者針對抽象進行設計與編程。?
?? ?2、橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用范圍具有一定的局限性
應用:
?? ?Collections類中的sort()方法;AWT;JDBC數據庫訪問接口API;
?
8、組合模式(Composite)
將對象組合成樹形結構以表示“部分-整體”的層次結構。
場景:
?? ?需求中體現部分與整體層次結構時,以及希望用戶可以忽略組合對象與單個對象的不同,統一使用組合結構中的所有對象時,就應該考慮使用組合模式了。
優點:
?? ?組合模式讓客戶可以一致的使用組合結構和單個對象。
缺點:
?? ?使設計變得更加抽象,對象的業務規則如果很復雜,則實現組合模式具有很大挑戰性,而且不是所有的方法都與葉子對象子類都有關聯。
應用:
?? ?JDK中AWT包和Swing包的設計是基于組合模式,在這些界面包中為用戶提供了大量的容器構件(如Container)和成員構件(如Checkbox、Button和TextComponent等),他們都是繼承、關聯自抽象組件類Component。
?
9、裝飾模式(Decorator)
動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更靈活。
場景:
?? ?裝飾模式是為了已有功能動態地添加更多功能的一種方式,當系統需要新功能的時候,是向舊類中添加新的代碼,這些新的代碼通常裝飾了原有類的核心職責或主要行為。裝飾著模式把每個要裝飾的功能放在單獨的類中,并讓這個類包裝它所要裝飾的對象,當需要執行特殊行為時,客戶代碼就可以在運行時根據需要有選擇的、按順序地使用裝飾功能包裝對象。
優點:
?? ?把類中的裝飾功能從類中搬移出去,簡化原有的類。有效的把類的核心職責和裝飾功能區分開,去除相關類中重復的裝飾邏輯。
缺點:
?? ?利用裝飾器模式,常常造成設計中有大量的小類,數量實在太多,可能會造成使用此API程序員的困擾。
應用:
?? ?Java I/O使用裝飾模式設計,JDK中還有很多類是使用裝飾模式設計的,如:Reader類、Writer類、OutputStream類等。
?
10、外觀模式(facade)
為子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
原則:
?? ?完美的體現了依賴倒轉原則和迪米特法則。
場景:
?? ?1、設計階段:需有意識的將不同的兩個層分離。
?? ?2、開發階段:增加外觀fa?ade提供一個簡單的接口,應對子類的重演和演化。
?? ?3、維護期間:使用fa?ade類,為遺留代碼提供清晰簡單的接口,讓新系統與fa?ade交互,fa?ade與遺留代碼交互所有復雜的工作。
優點:
?? ?1、客戶對子系統的使用變得簡單了,減少了與子系統的關聯對象,實現了子系統與客戶之間的松耦合關系。?
?? ?2、只是提供了一個訪問子系統的統一入口,并不影響用戶直接使用子系統類?
?? ?3、降低了大型軟件系統中的編譯依賴性,并簡化了系統在不同平臺之間的移植過程。
缺點:
?? ?1、不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性???
?? ?2、在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的源代碼,違背了“開閉原則”。
?
11、享元模式(Flyweight)
運用共享技術有效的支持大量細粒度的對象。
場景:
?? ?如果一個應用程序使用了大量的對象,而大量的這些對象造成了很大存儲開銷時就應該考慮使用享元模式;還有就是對象大多數狀態都可為外部狀態,如果刪除對象的外部狀態,那么可以用相對較少的共享對象取代很多組對象,此時可以考慮使用享元模式。
優點:
?? ?享元模式可以避免大量非常相似類的開銷。程序中,大量細粒度的類實例來表示數據,如果它們除了幾個參數外基本相同,那么把它們轉移到類實例的外面,在方法調用時將它們傳遞進來,就可以通過共享大幅度減少單個實例的數目。
缺點:
?? ?1、由于享元模式需要區分外部狀態和內部狀態,使得應用程序在某種程度上來說更加復雜化了。
?? ?2、為了使對象可以共享,享元模式需要將享元對象的狀態外部化,而讀取外部狀態使得運行時間變長。
應用:
?? ?String 類。
?
12、代理模式(proxy)
為其他對象提供一種代理以控制對這個對象的訪問。
原則:
?? ?代理模式就是在訪問對象時引入一定程度的間接性。(迪米特法則?)
場景:
?? ?1、遠程代理:為一個對象在不同的地址空間提供局部代表,這樣可以隱藏一個對象存在于不同地址空間的事實。【WebService,客戶端可以調用代理解決遠程訪問問題】
?? ?2、虛擬代理:根據需要創建開銷很大的對象,通過它來存放實例化需要很長時間地真實對象。【比如Html網頁的圖片,代理存儲的是真實圖片的路徑和尺寸】
?? ?3、安全代理:用來控制真實對象的訪問權限。
?? ?4、智能指引:當調用真實的對象時,代理處理另一些事。【如計算機真實對象的引用次數,代理在訪問一個對象的時候回附加一些內務處理,檢查對象是否被鎖定、是否該釋放、是否該裝入內存等等】
優點:
?? ?1、代理模式能將代理對象與真正被調用的對象分離,在一定程度上降低了系統的耦合度。
?? ?2、代理模式在客戶端和目標對象之間起到一個中介作用,這樣可以起到保護目標對象的作用。代理對象也可以對目標對象調用之前進行其他操作。
缺點:
?? ?1、在客戶端和目標對象增加一個代理對象,會造成請求處理速度變慢。
?? ?2、增加了系統的復雜度。
應用:
?? ?java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力。
?
13、觀察者模式(Publish/Subscribe) 【又名 發布-訂閱模式】
定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,讓它們能夠自動更新自己。
場景:
?? ?將一個系統分割成一系列互相協作的類,有一個缺點:需要維護相關對象間的一致性。緊密的耦合會給維護和擴展帶來不便。觀察者模式就是為了解耦而誕生的,讓原本一個對象依賴另一個對象的關系,變成了兩方都依賴于抽象,而不再依賴于具體,從而使得各自的變化都不會影響另一邊的變化。
優點:
?? ?解耦。
缺點:
?? ?如果在被觀察者之間有循環依賴的話,被觀察者會觸發它們之間進行循環調用,導致系統崩潰。在使用觀察者模式是要特別注意這一點。
應用:
?? ?java.util.Observer, java類庫實現觀察著(Observer)模式的類和接口。
?
14、模板方法模式(Template Method)
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。
原則:
?? ?代碼復用平臺。
場景:
?? ?遇到由一系列步驟構成的過程需要執行,這個過程從高層次上看是相同的,但是有些步驟的實現可能不同,這個時候就需要考慮用模板方法模式了。
優點:
?? ?模板方法模式是通過把不變行為搬移到超類,去除子類中重復代碼來實現它的優勢,提供了一個代碼復用平臺,幫助子類擺脫重復的不變行為的糾纏。
缺點:
?? ?如果父類中可變的基本方法太多,將會導致類的個數增加,系統更加龐大。
應用:
?? ?AbstractClass抽象類里面的TemplateMethod()就是模板方法。
?
15、命令模式(command)
將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。
原則:
?? ?敏捷開發原則
場景:
?? ?對請求排隊或記錄請求日志,以及支持可撤銷的操作等行為。
優點:
?? ?1、命令模式把請求一個操作的對象與知道怎么執行一個操作的對象分割開。
?? ?2、它能較容易的設計一個命令隊列。
?? ?3、在需要的情況下,可以較容易的將命令記入日志。
?? ?4、允許接收請求的一方決定是否要否決請求。
?? ?5、可以容易的實現對請求的撤銷和重做。
?? ?6、由于加進新的具體命令類不影響其他類,因此增加新的具體命令類很容易。
缺點:
?? ?會增加系統的復雜性,這里的復雜性應該主要指的是類的數量。
應用:
?? ?1、java.util.Timer類中scheduleXXX()方法
?? ?2、java Concurrency Executor execute()方法
?? ?3、java.lang.reflect.Methodinvoke()方法
?
16、狀態模式(state)
當一個對象的內在狀態改變時,允許改變其行為,這個對象看起來像是改變了其類。
原則:
?? ?單一職責原則
場景:
?? ?當一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為時,可以考慮使用狀態模式了。
優點:
?? ?狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過于復雜的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把復雜的判斷邏輯簡化。【消除龐大的條件分支語句】。
缺點:
?? ?違背開放-封閉原則
應用:
?? ?1、java.util.Iterator
?? ?2、javax.faces.lifecycle.LifeCycle#execute()
?
17、職責鏈模式(chain of responsibility)
使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關系。將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
場景:
?? ?當客戶提交一個請求時,請求是沿鏈傳遞直至有一個對象負責處理它。
優點:
?? ?使得接收者和發送者都沒有對方的明確信息,且鏈中對象自己也不知道鏈結構,結果是職責鏈可以簡化對象的相互連接,它們只需要保持一個指向其后繼者的引用,而不需要保持它所有的候選接收者的引用。開發者可以隨時的增加或者修改處理一個請求的結構,增強了給對象指派職責的靈活性。
缺點:
?? ?一個請求極有可能到了鏈的末端都得不到處理,或者因為沒有正確配置而得不到處理。
?
18、解釋器模式(interpreter)
給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
原則:
?? ?依賴倒轉原則
場景:
?? ?如果一種特定類型問題發生的頻率足夠高,那么可能就值得將該問題的各個實例表述為一個簡單語句中的句子。這樣就可以構建一個解釋器,該解釋器通過解釋這些句子來解決該問題。當一個語言需要執行,并且你可將該語言中的句子表示為一個抽象語法樹時,可以用解釋器模式。
優點:
?? ?解釋器很容易改變和擴展文法,因為該模式使用類來表示文法規則,可以使用繼承來改變或擴展文法,也比較容易實現文法。因為定義抽象語法樹中各個節點的類的實現大體類似,這些類都易于直接編寫。
缺點:
?? ?解釋器模式為文法中的每一條規則至少定義了一個類,因此包含許多規則的文法可能難以管理和維護,建議當文法非常復雜時,使用其他技術(語法分析程序、編譯器生成器)。
應用:
?? ?1、java.util.Pattern
?? ?2、java.text.Normalizer
?? ?3、java.text.Format
?? ?4、javax.el.ELResolver
?
19、中介者模式(mediator)
用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯示的相互引用,從而使其耦合松散,而且可以獨立的改變它們之間的交互。
場景:
?? ?一般應用于一組對象以定義良好但是復雜的方式進行通信的場合,以及想定制一個分布在多個類的行為,而又不想生成太多子類的場合。【例如,Form窗體,或者aspx頁面】。
優點:
?? ?1、抽象中介者類(Mediator)減少了抽象同事類(colleague)之間的耦合,是的可以獨立的改變和復用各個類。
?? ?2、由于把對象如何協作進行了抽象,將中介作為一個獨立的概念并將其封裝在一個對象中,這樣關注的對象就從對象各自本身的行為轉移到它們之間的交互上來,也就是站在一個更宏觀的角度去看待系統。
缺點:
?? ?控制集中化導致了中介者的復雜化。
應用:
?? ?1、java.util.Timer
?? ?2、java.util.concurrent.Executor#execute()
?? ?3、java.util.concurrent.ExecutorService#submit()
?? ?4、java.lang.reflect.Method#invoke()
?
20、訪問者模式 (Vistor) 生成器模式
(GoF中最復雜的一個模式)表示一個作用于某對象結構中的各元素的操作,它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
場景:
?? ?訪問者模式適合有穩定的數據結構、又有易于變化的算法】訪問者模式適用于數據結構相對穩定的系統,它把數據結構和作用于結構上的操作之間的耦合解脫開,是的操作集合可以相對自由的演化。訪問者模式的目的是要把處理從數據結構中分離出來。
優點:
?? ?增加新的操作很容易。新的操作就是新的訪問者。
缺點:
?? ?很難增加新的數據結構。
應用:
?? ?1、javax.lang.model.element.AnnotationValue和AnnotationValueVisitor
?? ?2、javax.lang.model.element.Element和ElementVisitor
?? ?3、javax.lang.model.type.TypeMirror和TypeVisitor
?
21、策略模式(strategy)
它定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化不會影響到使用算法的用戶。
場景:
?? ?策略模式不僅可以用來封裝算法,幾乎可以封裝縫合類型的規則,不同的業務邏輯都可以考慮用策略模式處理變化。
優點:
?? ?策略模式的策略類為上下文定義了一系列可供重用的算法或行為,繼承有助于析取出這些算法中的公共功能。另外,策略模式簡化了單元測試,因為每一個算法都有自己的類,可以通過自己的接口單獨測試。當不同的行為堆砌在一個類中,很難避免使用switch語句。但是將這些行為封裝在一個一個獨立的策略類中,可以在使用這些行為的類中消除條件語句
缺點:
?? ?基本的策略模式,選擇權在客戶端,具體實現轉給策略模式的上下文對象。這并不好。使用策略模式和工廠類結合,可以減輕客戶端的職責。但是還是不夠完美,使用反射才能真正快樂。
應用:
?? ?1、java.util.Comparator#compare()
?? ?2、javax.servlet.http.HttpServlet
?? ?3、javax.servlet.Filter#doFilter()
?
22、備忘錄模式(Memento)
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態,這樣以后就可將該對象恢復到原先保存的狀態。
場景:
?? ?Memento封裝要保存的細節,適合功能負責但需要維護或記錄屬性歷史的類,或者是需要保存的屬性只是眾多屬性中的一個小部分。
優點:
?? ?使用備忘錄模式可以把復雜的發起人內部信息對其他的對象屏蔽起來,從而可以恰當地保持封裝的邊界。
缺點:
?? ?如果發起人角色的狀態需要完整地存儲到備忘錄對象中,那么在資源消耗上面備忘錄對象會很昂貴。
應用:
?? ?1、java.util.Date
?? ?2、java.io.Serializable
?
23、迭代器模式(Iterator)
提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部表示。
場景:
?? ?當需要對聚集有多種方式遍歷時,可以考慮使用迭代器。
優點:
?? ?迭代器模式就是分離了集合對象的遍歷行為,抽象出一個迭代器來負責,這樣既可以做到不暴露集合的內部結構,又可以讓外部代碼透明的訪問集合內部的數據。
缺點:
?? ?由于迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的復雜性。
應用:
?? ?collection容器使用了迭代器模式
?
?
總結
以上是生活随笔為你收集整理的GOF设计模式(概念、原则、场景、优点、缺点、应用)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: awr报告分析 mysql_AWR报告的
- 下一篇: 设计模式-GRASP V.S GoF