java 設(shè)計模式-簡述

編程設(shè)計模式

六大基本原則

總原則:開閉原則(Open Close Principle,OCP)

開:對拓展開放,允許拓展。

閉:對修改關(guān)閉,禁止修改。

其含義在于拓展程序時,不要修改原有的代碼,而是僅拓展。這是為了使程序的拓展性更好,易于維護和升級,當(dāng)然,這樣會導(dǎo)致代碼臃腫,但利遠遠大于弊。

主要思想:在于使用接口和抽象類。

1:單一職責(zé)原則

每個類應(yīng)該實現(xiàn)單一的職責(zé),若存在不同種修改的原因,應(yīng)該將對象進行拆分。

2:里氏替換原則(Liskov Substitution Principle,LSP) /* 子可替父,正常工作 */

面向?qū)ο笤O(shè)計的基本原則之一。其主要思想在于任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。其作為開閉原則的補充,描述了對實現(xiàn)抽象化的具體步驟的規(guī)范。

只有當(dāng)派生類可以替換基類,且軟件功能不受影響時,基類才能真正被復(fù)用。當(dāng)然,衍生類能夠在基類的基礎(chǔ)上增加新的行為。

3:依賴倒轉(zhuǎn)原則(Dependency Inversion Principle,DIP) /* 接口交互 ,不看具體 */

作為開閉原則的基礎(chǔ),在面向接口編程時,依賴于抽象類,而非具體的實現(xiàn)類。寫代碼中,用到具體類時,不與具體類進行交互,而是與其接口進行交互。

4:接口隔離原則(Interface Segregation Principle,ISP) /* 細分接口,功能純粹 */

每個接口不存在子類不需要,但必須實現(xiàn)的方法。如果有,就要將接口拆分。使用多個隔離接口,比使用單個(合多為一)接口更好。

5:迪米特原則(最少知道原則)(Demeter Principle,DP)

一個類A,對要用到的類B的信息(如作為其成員變量),知道的越少越好。無論對類B本身有多復(fù)雜,都應(yīng)該只使用public來使用它,將其復(fù)雜的邏輯封裝在方法的內(nèi)部。這樣在變動時,對類A的影響會最小。

另一個陳述方式是:只與直接的朋友通信。

類之間只要有耦合關(guān)系,就叫朋友關(guān)系。耦合分為依賴、關(guān)聯(lián)、聚合、組合等。若類B作為類A成員變量、方法參數(shù)、方法返回值,則為直接朋友;若作為函數(shù)內(nèi)局部變量、臨時變量則非直接朋友。陌生的類,不要作為局部變量出現(xiàn)在類中。

6:合成復(fù)用原則(Composite Reuse Principle,CRP)

盡量首先使用合成/聚合的方式,而不是使用繼承。先考慮將類作為成員變量、函數(shù)參數(shù),而不是先考慮繼承。

java的23種設(shè)計模式

創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。

結(jié)構(gòu)型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪問者模式、中介者模式、解釋器模式。

創(chuàng)建型模式

概述:用什么方法創(chuàng)建類和對象。

包含:工廠方法模式、抽象工廠模式、單例模式、原型模式、建造者模式。

0.簡單工廠模式(不屬于23種之一)

以其,可以延伸出更好的方法,所以先探討這個。適用于:大量的產(chǎn)品(接口的具體類)需要創(chuàng)建。

三種簡單工廠模式:普通、多方法、靜態(tài)方法。

以下是在測試Test類中,調(diào)用了工廠類和接口類。以接口類作為基類,標(biāo)識符指向?qū)崿F(xiàn)對象:工廠類中函數(shù)(produce)返回的接口實例。

Test類中 普通 多方法 靜態(tài)方法
接口類(負(fù)責(zé)指向具體對象) 需要實例化。指向工廠produce返回對象。 需要實例化。指向工廠produce返回對象。 需要實例化。指向工廠produce返回對象。
工廠類(生成接口實例) 需要實例化。一個produce函數(shù)。需要參數(shù),來進行對接口的選擇??赡芤邆?/td> 需要實例化。多個produceX函數(shù)。每個返回不同的接口實現(xiàn)對象。 不需要實例化。也是多個produceX。負(fù)責(zé)返回單一的接口實現(xiàn)對象,但其為靜態(tài)函數(shù)。

可以看出,靜態(tài)工廠方法,比前兩種更加優(yōu)越。其不需要傳入?yún)?shù),所以不必考慮參數(shù)不符合的糾錯。比多方法又不需要實例化。

1.工廠方法模式(以下屬于23種)

作為簡單工廠的最終實現(xiàn),其根據(jù)代碼 “不修改,只拓展” 的原則:

①有工廠接口。派生出多個具體工廠類,每廠只生產(chǎn)一種對象。

②有產(chǎn)品接口(如Sender,具體實現(xiàn)為EmailSender、SmsSender等)。派生出多個具體產(chǎn)品類。每個具體產(chǎn)品都有唯一工廠創(chuàng)建。

當(dāng)拓展時,新建一個產(chǎn)品類,就對應(yīng)新建一個工廠類。不修改,只拓展。

反思:這種思想會導(dǎo)致大量臃腫的代碼,應(yīng)配合其他方法使用,而非獨一。

2.抽象工廠模式

工廠方法模式:更像現(xiàn)實中工廠的流水線,而非工廠。因為一個具體工廠類,只能生產(chǎn)一個產(chǎn)品。

抽象工廠模式:更像現(xiàn)實中工廠。其有多個抽象工廠,每個工廠,能生產(chǎn)一個接口下的不同具體實例。

對比 工廠接口 具體工廠 產(chǎn)品接口 具體產(chǎn)品
工廠方法模式 1個 k個 1個 k個
抽象方法模式 n個 n或n*k個 k個 n*k個

抽象方法模式中,每個具體工廠可以生產(chǎn)一個產(chǎn)品(簡單工廠模式),或者生產(chǎn)多個產(chǎn)品(工廠方法模式)。

當(dāng)然,如采用工廠方法模式(不修改,僅拓展),會導(dǎo)致很多的類,采用簡單工廠模式會更加簡潔(修改并拓展)。

3.單例模式

單例對象是一種常用的設(shè)計模式??杀WC在jvm中,每個對象實例僅存在一個(一個類只可以產(chǎn)生同一個對象)。

class A{}

public class Singleton {
    private Singleton() {};
    public static Singleton getInstance() {
        return SingleFactory.instance;
    }
    
    private static class SingleFactory{
        private static Singleton instance =new Singleton();
    };
    
    public static void main(String [] args) {
        Singleton x =Singleton.getInstance();
        Singleton y=Singleton.getInstance();
        System.out.println("x=y ? "+(x==y));/*使用了單例模式,x、y指向同一實例:輸出true*/
        
        A a = new A();
        A a1 = new A();
        System.out.println("a=a1 ? "+(a==a1));/*正常實例化的兩個對象,a、a1指向不同實例:輸出                                                    false8*/        
    }   
}

優(yōu)點:

①某些類尤其是大型類,當(dāng)其頻繁的創(chuàng)建時,對系統(tǒng)開銷很大。

②省去了new操作符,降低了系統(tǒng)內(nèi)存的使用頻率,減輕GC(垃圾回收)壓力。

③某些類,如交易所的核心交易引擎,只能有一個存在,不能創(chuàng)建多個,否則會出大錯。使用單例可以避免出現(xiàn)這些麻煩。

實現(xiàn):

①將類構(gòu)造函數(shù)變成私有,禁止自動構(gòu)造。

②提供一個getInstance()方法,返回該類對象。

③getInstance()函數(shù)中,對獲取對象的方法,要注意多線程出錯問題,可采用synchronized進行必要鎖定。

實例可以看:https://www.cnblogs.com/onetwo/p/9933417.html

4.建造者模式

Builder和Factory不同之處,在于Builder可以將多種類型,復(fù)合起來:其內(nèi)部可以包含一個或多個List<Interface/abstract>。

一個List<Interface/abstract>:又可以包含多個不同的具體派生類、實現(xiàn)類實例。

如同翁凱老師在java課中講的FoxAndRabbit實例,F(xiàn)iled類中,包含了Cell [ ] [ ] Animals的數(shù)組。里面可以存放狐貍、兔子或空。動物都implements (interface) Cell的。

5.原型模式(Prototype)

概述:用復(fù)制clone()代替new,在類中有大量對象時,復(fù)制比new一個對象更高效。

原型模式通常適用于以下場景。

  • 對象之間相同或相似,即只是個別的幾個屬性不同的時候。
  • 對象的創(chuàng)建過程比較麻煩,但復(fù)制比較簡單的時候

實現(xiàn):

①該原型類需要implements Cloneable。

②重寫clone()函數(shù),通常直接return super.clone();

③測試中,對象不新建,而是復(fù)制。 x != x.clone();

淺拷貝:拷貝時創(chuàng)建一個新的對象,對象中的基本數(shù)據(jù)類型會復(fù)制,而對屬性是引用類型(如對象成員變量)不會創(chuàng)建新的對象,而是使用與之前的對象指向同一個內(nèi)存地址。即:

x!=x.clone();

x.b == x.clone().b; /* b為class B類型的靜態(tài)成員變量 */

深拷貝:拷貝時創(chuàng)建一個新的對象,并且所有屬性都是新對象(指向新的內(nèi)存地址)

結(jié)構(gòu)型模式

概述:用什么方法將類和對象布局(組合復(fù)用)成更大的結(jié)構(gòu)。
分為:類結(jié)構(gòu)型模式對象結(jié)構(gòu)型模式。前者采用繼承機制來組織接口和類,后者釆用組合或聚合來組合對象。

由于組合關(guān)系或聚合關(guān)系,比類的繼承關(guān)系耦合性低,所以通常對象結(jié)構(gòu)型模式具備更強靈活性。

1.適配器模式

在軟件設(shè)計中可能出現(xiàn):需要開發(fā)的具有某種業(yè)務(wù)功能的組件在現(xiàn)有的組件庫中已經(jīng)存在,但它們與當(dāng)前系統(tǒng)的接口規(guī)范不兼容,如果重新開發(fā)這些組件成本又很高,這時用適配器模式能很好地解決這些問題。

分為:類適配器、對象適配器(更多用)。

主要優(yōu)點:

  • 客戶端通過適配器可以透明地調(diào)用目標(biāo)接口。
  • 復(fù)用了現(xiàn)存的類,程序員不需要修改原有代碼而重用現(xiàn)有的適配者類。
  • 將目標(biāo)類和適配者類解耦,解決了目標(biāo)類和適配者類接口不一致的問題。

其缺點是:對類適配器來說,更換適配器的實現(xiàn)過程比較復(fù)雜。

方式:如main函數(shù)中需要調(diào)用request()函數(shù),而數(shù)據(jù)庫里有個可以實現(xiàn)這個功能的函數(shù),但其接口為SpecialRequest(),此時,我們將SpecialReaquest()函數(shù)進行包裝,用繼承或包含類對象的方式,給出一個request接口,里面調(diào)用SpecialRequest()。

其他模式都是從適配器模式,延伸出來的。


適配器模式.PNG

2.裝飾模式

對已有的類,進行功能拓展。

方法:建立一個新類,與原有類要implements same interfaces,然后重寫方法,方法中,可以調(diào)用已有類的同名方法,并對其拓展。

3.代理模式(Proxy)

對某個類A進行代理,用新的代理類B接口來替換其接口,當(dāng)需要對A進行訪問時,不直接訪問A,而是通過B訪問A。

是為了對被代理類,進行保護,如訪問遠程對象很大(視頻、大圖),或服務(wù)器中的數(shù)據(jù)庫,出于安全不能讓客戶端直接訪問,而是通過中間類。

主要優(yōu)點:

  • 代理模式在客戶端與目標(biāo)對象之間起到一個中介作用和保護目標(biāo)對象的作用;
  • 代理對象可以擴展目標(biāo)對象的功能; (拓展不修改)
  • 代理模式能將客戶端與目標(biāo)對象分離,在一定程度上降低了系統(tǒng)的耦合度;

主要缺點:

  • 在客戶端和目標(biāo)對象之間增加一個代理對象,會造成請求處理速度變慢;
  • 增加了系統(tǒng)的復(fù)雜度;

應(yīng)用場景:

  • 遠程代理:這種方式通常是為了隱藏目標(biāo)對象存在于不同地址空間的事實,方便客戶端訪問。例如,用戶申請某些網(wǎng)盤空間時,會在用戶的文件系統(tǒng)中建立一個虛擬的硬盤,用戶訪問虛擬硬盤時實際訪問的是網(wǎng)盤空間。
  • 虛擬代理:這種方式通常用于要創(chuàng)建的目標(biāo)對象開銷很大時。例如,下載一幅很大的圖像需要很長時間,因某種計算比較復(fù)雜而短時間無法完成,這時可以先用小比例的虛擬代理替換真實的對象,消除用戶對服務(wù)器慢的感覺。
  • 安全代理:這種方式通常用于控制不同種類客戶對真實對象的訪問權(quán)限。
  • 智能指引:主要用于調(diào)用目標(biāo)對象時,代理附加一些額外的處理功能。例如,增加計算真實對象的引用次數(shù)的功能,這樣當(dāng)該對象沒有被引用時,就可以自動釋放它。
  • 延遲加載:指為了提高系統(tǒng)的性能,延遲對目標(biāo)的加載。例如,Hibernate 中就存在屬性的延遲加載和關(guān)聯(lián)表的延時加載。

4.外觀模式(Facade)

迪米特原則(最少知道原則)的具體實現(xiàn)。將多個相關(guān)聯(lián)類,組合到一個類Conbine中(以成員變量等形式)。Conbine類提供統(tǒng)一的接口,對每個組件類統(tǒng)一操作,降低了客戶端和組件類的耦合性,也降低了組件類之間互相關(guān)聯(lián)的耦合性。

舉例:Computer類包含了Cpu類、Memory類、Disk類。Computer::start中,會調(diào)用組件類的start函數(shù)。

應(yīng)用場景

  • 對分層結(jié)構(gòu)系統(tǒng)構(gòu)建時,使用外觀模式定義子系統(tǒng)中每層的入口點可以簡化子系統(tǒng)之間的依賴關(guān)系。

  • 當(dāng)一個復(fù)雜系統(tǒng)的子系統(tǒng)很多時,外觀模式可以為系統(tǒng)設(shè)計一個簡單的接口供外界訪問。

  • 當(dāng)客戶端與多個子系統(tǒng)之間存在很大的聯(lián)系時,引入外觀模式可將它們分離,從而提高子系統(tǒng)的獨立性和可移植性。

限制:

  • 不能很好地限制客戶使用子系統(tǒng)類。

  • 增加新的子系統(tǒng)可能需要修改外觀類或客戶端的源代碼,違背了“開閉原則”。

5.橋接模式(Bridge)

概述:用組合關(guān)系代替繼承關(guān)系。

優(yōu)點:

  • 由于抽象與實現(xiàn)分離,所以擴展能力強;
  • 其實現(xiàn)細節(jié)對客戶透明。

缺點:

由于聚合關(guān)系建立在抽象層,要求開發(fā)者針對抽象化進行設(shè)計與編程,這增加了系統(tǒng)的理解與設(shè)計難度。

如:對于女士包:顏色、型號、挎包、錢包。

不是對女士包進行一個抽象,具體實現(xiàn)時包含各自的款型和顏色。而是:提出顏色類、包型類(派生出錢包、挎包)。對于每個具體的包,會包含一個顏色類的實體。

用組合代替了繼承。

應(yīng)用場景:

  1. 當(dāng)一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展時。
  2. 當(dāng)一個系統(tǒng)不希望使用繼承或因為多層次繼承導(dǎo)致系統(tǒng)類的個數(shù)急劇增加時。
  3. 當(dāng)一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性時。

6.組合模式(Composite)

概述:將對象組合成形如tree的關(guān)系。如樹結(jié)構(gòu)便是用了組合模式。(部分-整體形式)

主要優(yōu)點:

  • 組合模式使得客戶端代碼可以一致地處理單個對象和組合對象,無須關(guān)心自己處理的是單個對象,還是組合對象,這簡化了客戶端代碼;
  • 更容易在組合體內(nèi)加入新的對象,客戶端不會因為加入了新的對象而更改源代碼,滿足“開閉原則”;

主要缺點:

  • 設(shè)計較復(fù)雜,客戶端需要花更多時間理清類之間的層次關(guān)系;

  • 不容易限制容器中的構(gòu)件;

  • 不容易用繼承的方法來增加構(gòu)件的新功能;

7.享元模式(Flyweight)

概述:當(dāng)需要多次生成對象,且他們僅有部分不同(如五子棋中的棋子,顯示器中的像素點)。建立共享對象,使新建對象的相同部分指向其對象中元素。(通常與工廠模式搭配)

優(yōu)點:相同對象只保存一份。降低數(shù)量,降低內(nèi)存壓力。

缺點:

  • 為使對象共享,需使對象中區(qū)別元素可視化,外部可訪問,增加程序復(fù)雜性。
  • 讀取該模式下的外部狀態(tài),會使運行時間稍微變長。

行為型模式

概述:行為型模式用于描述程序在運行時復(fù)雜的流程控制,即描述多個類或?qū)ο笾g怎樣相互協(xié)作共同完成單個對象都無法單獨完成的任務(wù),它涉及算法與對象間職責(zé)的分配。

行為型模式分為類行為模式對象行為模式(*),前者采用繼承機制來在類間分派行為,后者采用組合或聚合在對象間分配行為。

示意圖

行為型模式.PNG

1.策略模式(Strategy)

概述:可理解為選擇模式。一個類中,針對某一個函數(shù),可以選擇不同的對象來實現(xiàn)(同一個基類或接口),通過輸入的參數(shù)來確定。如輸出“x+y”、“x*y”,可先解析出操作符,然后調(diào)用不同方法來實現(xiàn);還有現(xiàn)實中的超市活動,可以通過送積分、送現(xiàn)金等方法。

主要優(yōu)點:

  1. 多重條件語句不易維護,而使用策略模式可以避免使用多重條件語句。
  2. 策略模式提供了一系列的可供重用的算法族,恰當(dāng)使用繼承可以把算法族的公共代碼轉(zhuǎn)移到父類里面,從而避免重復(fù)的代碼。
  3. 策略模式可以提供相同行為的不同實現(xiàn),客戶可以根據(jù)不同時間或空間要求選擇不同的。
  4. 策略模式提供了對開閉原則的完美支持,可以在不修改原代碼的情況下,靈活增加新算法。
  5. 策略模式把算法的使用放到環(huán)境類中,而算法的實現(xiàn)移到具體策略類中,實現(xiàn)了二者的分離。

主要缺點:

  1. 客戶端必須理解所有策略算法的區(qū)別,以便適時選擇恰當(dāng)?shù)乃惴悺?/li>
  2. 策略模式造成很多的策略類。

2.模板方法模式(Template Method)

概述:一個抽象類,很多派生類。通過對抽象類的調(diào)用,使用派生類的重載方法。

3.觀察者模式(Obsever)

概述:指多個對象間存在一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。這種模式有時又稱作發(fā)布-訂閱模式、模型-視圖模式,它是對象行為型模式。

如同Excel中,數(shù)據(jù)變化,會導(dǎo)致示意圖(折線圖、餅狀圖)發(fā)生變化。

包含此模式以后的四個模式,都是類與類(對象)之間的關(guān)系,不涉及繼承。

實現(xiàn):

  1. 抽象主題角色:也叫抽象目標(biāo)類,它提供了一個用于保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。(Subject)
  2. 具體主題角色:也叫具體目標(biāo)類,它實現(xiàn)抽象目標(biāo)中的通知方法,當(dāng)具體主題的內(nèi)部狀態(tài)發(fā)生改變時,通知所有注冊過的觀察者對象。(Concrete Subject)
  3. 抽象觀察者角色:它是一個抽象類或接口,它包含了一個更新自己的抽象方法,當(dāng)接到具體主題的更改通知時被調(diào)用。(Observer)
  4. 具體觀察者角色:實現(xiàn)抽象觀察者中定義的抽象方法,以便在得到目標(biāo)的更改通知時更新自身的狀態(tài)。(Concrete Observer)

4.迭代器模式(Iterator)

概述:建立一個迭代器對象來管理數(shù)據(jù)。

它在客戶訪問類與聚合類之間插入一個迭代器,這分離了聚合對象與其遍歷行為,對客戶也隱藏了其內(nèi)部細節(jié),且滿足“單一職責(zé)原則”和“開閉原則”,如 Java 中的 Collection、List、Set、Map 等都包含了迭代器。

主要優(yōu)點:

  1. 訪問一個聚合對象的內(nèi)容而無須暴露它的內(nèi)部表示。
  2. 遍歷任務(wù)交由迭代器完成,這簡化了聚合類。
  3. 它支持以不同方式遍歷一個聚合,甚至可以自定義迭代器的子類以支持新的遍歷。
  4. 增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
  5. 封裝性良好,為遍歷不同的聚合結(jié)構(gòu)提供一個統(tǒng)一的接口。

主要缺點:增加了類的個數(shù),這在一定程度上增加了系統(tǒng)的復(fù)雜性。

迭代器模式主要包含以下角色。

  1. 抽象聚合角色:定義存儲、添加、刪除聚合對象以及創(chuàng)建迭代器對象的接口。(Aggregate)
  2. 具體聚合角色:實現(xiàn)抽象聚合類,返回一個具體迭代器的實例。(ConcreteAggregate)
  3. 抽象迭代器角色:定義訪問和遍歷聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。(Iterator)
  4. 具體迭代器角色:實現(xiàn)抽象迭代器接口中所定義的方法,完成對聚合對象的遍歷,記錄遍歷的當(dāng)前位置。(Concretelterator)

5.責(zé)任鏈模式(Chain of Responsibility)

概述:為了避免請求發(fā)送者與多個請求處理者耦合在一起,將所有請求的處理者通過前一對象記住其下一個對象的引用而連成一條鏈;當(dāng)有請求發(fā)生時,可將請求沿著這條鏈傳遞,直到有對象處理它為止。

在責(zé)任鏈模式中,客戶只需要將請求發(fā)送到責(zé)任鏈上即可,無須關(guān)心請求的處理細節(jié)和請求的傳遞過程,所以責(zé)任鏈將請求的發(fā)送者和請求的處理者解耦了。

責(zé)任鏈模式是一種對象行為型模式。

主要優(yōu)點:

  1. 降低了對象之間的耦合度。該模式使得一個對象無須知道到底是哪一個對象處理其請求以及鏈的結(jié)構(gòu),發(fā)送者和接收者也無須擁有對方的明確信息。
  2. 增強了系統(tǒng)的可擴展性??梢愿鶕?jù)需要增加新的請求處理類,滿足開閉原則。
  3. 增強了給對象指派職責(zé)的靈活性。當(dāng)工作流程發(fā)生變化,可以動態(tài)地改變鏈內(nèi)的成員或者調(diào)動它們的次序,也可動態(tài)地新增或者刪除責(zé)任。
  4. 責(zé)任鏈簡化了對象之間的連接。每個對象只需保持一個指向其后繼者的引用,不需保持其他所有處理者的引用,這避免了使用眾多的 if 或者 if···else 語句。
  5. 責(zé)任分擔(dān)。每個類只需要處理自己該處理的工作,不該處理的傳遞給下一個對象完成,明確各類的責(zé)任范圍,符合類的單一職責(zé)原則。

主要缺點:

  1. 不能保證每個請求一定被處理。由于一個請求沒有明確的接收者,所以不能保證它一定會被處理,該請求可能一直傳到鏈的末端都得不到處理。
  2. 對比較長的職責(zé)鏈,請求的處理可能涉及多個處理對象,系統(tǒng)性能將受到一定影響。
  3. 職責(zé)鏈建立的合理性要靠客戶端來保證,增加了客戶端的復(fù)雜性,可能會由于職責(zé)鏈的錯誤設(shè)置而導(dǎo)致系統(tǒng)出錯,如可能會造成循環(huán)調(diào)用。

6.命令模式(Command)

概述:將一個請求封裝為一個對象,使發(fā)出請求和執(zhí)行請求的對象分割開。這樣兩者之間通過命令對象進行溝通,這樣方便將命令對象進行儲存、傳遞、調(diào)用、增加與管理。

在軟件開發(fā)系統(tǒng)中,常常出現(xiàn)“方法的請求者”與“方法的實現(xiàn)者”之間存在緊密的耦合關(guān)系。這不利于軟件功能的擴展與維護。例如,想對行為進行“撤銷、重做、記錄”等處理都很不方便,因此“如何將方法的請求者與方法的實現(xiàn)者解耦?”變得很重要,命令模式能很好地解決這個問題。

主要優(yōu)點:

  1. 降低系統(tǒng)的耦合度。命令模式能將調(diào)用操作的對象與實現(xiàn)該操作的對象解耦。
  2. 增加或刪除命令非常方便。采用命令模式增加與刪除命令不會影響其他類,它滿足“開閉原則”,對擴展比較靈活。
  3. 可以實現(xiàn)宏命令。命令模式可以與組合模式結(jié)合,將多個命令裝配成一個組合命令,即宏命令。
  4. 方便實現(xiàn) Undo 和 Redo 操作。命令模式可以與后面介紹的備忘錄模式結(jié)合,實現(xiàn)命令的撤銷與恢復(fù)。

主要缺點:

可能產(chǎn)生大量具體命令類。因為計對每一個具體操作都需要設(shè)計一個具體命令類,這將增加系統(tǒng)的復(fù)雜性。

7.備忘錄模式(Momento)

概述:在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài),以便以后當(dāng)需要時能將該對象恢復(fù)到原先保存的狀態(tài)。該模式又叫快照模式?!皞浞?恢復(fù)”模式

每個人都有犯錯誤的時候,都希望有種“后悔藥”能彌補自己的過失,讓自己重新開始,但現(xiàn)實是殘酷的。在計算機應(yīng)用中,客戶同樣會常常犯錯誤,能否提供“后悔藥”給他們呢?當(dāng)然是可以的,而且是有必要的。這個功能由“備忘錄模式”來實現(xiàn)。

其實很多應(yīng)用軟件都提供了這項功能,如 Word、記事本、Photoshop、Eclipse 等軟件在編輯時按 Ctrl+Z 組合鍵時能撤銷當(dāng)前操作,使文檔恢復(fù)到之前的狀態(tài);還有在 IE 中的后退鍵、數(shù)據(jù)庫事務(wù)管理中的回滾操作、玩游戲時的中間結(jié)果存檔功能、數(shù)據(jù)庫與操作系統(tǒng)的備份操作、棋類游戲中的悔棋功能等都屬于這類。

備忘錄模式是一種對象行為型模式。

起源類 備忘錄類 存儲備忘錄類
功能 提供一個可恢復(fù)的接口,將參數(shù)設(shè)置替換自己的參數(shù) 保存起源類對象必需的參數(shù) 存儲了多條備忘錄,可以多次撤銷

主要優(yōu)點:。

  • 提供了一種可以恢復(fù)狀態(tài)的機制。當(dāng)用戶需要時能夠比較方便地將數(shù)據(jù)恢復(fù)到某個歷史的狀態(tài)。
  • 實現(xiàn)了內(nèi)部狀態(tài)的封裝。除了創(chuàng)建它的發(fā)起人之外,其他對象都不能夠訪問這些狀態(tài)信息。
  • 簡化了發(fā)起人類。發(fā)起人不需要管理和保存其內(nèi)部狀態(tài)的各個備份,所有狀態(tài)信息都保存在備忘錄中,并由管理者進行管理,這符合單一職責(zé)原則。

主要缺點:

資源消耗大。如果要保存的內(nèi)部狀態(tài)信息過多或者特別頻繁,將會占用比較大的內(nèi)存資源。

實現(xiàn):

  1. 發(fā)起人角色:記錄當(dāng)前時刻的內(nèi)部狀態(tài)信息,提供創(chuàng)建備忘錄和恢復(fù)備忘錄數(shù)據(jù)的功能,實現(xiàn)其他業(yè)務(wù)功能,它可以訪問備忘錄里的所有信息。(Originator)
  2. 備忘錄角色:負(fù)責(zé)存儲發(fā)起人的內(nèi)部狀態(tài),在需要的時候提供這些內(nèi)部狀態(tài)給發(fā)起人。(Memento)
  3. 管理者角色:對備忘錄進行管理,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內(nèi)容進行訪問與修改。(Caretaker)

8.狀態(tài)模式(State)

概述:對有狀態(tài)的對象,把復(fù)雜的“判斷邏輯”提取到不同的狀態(tài)對象中,允許狀態(tài)對象在其內(nèi)部狀態(tài)發(fā)生改變時改變其行為。

在軟件開發(fā)過程中,應(yīng)用程序中的有些對象可能會根據(jù)不同的情況做出不同的行為,我們把這種對象稱為有狀態(tài)的對象,而把影響對象行為的一個或多個動態(tài)變化的屬性稱為狀態(tài)。當(dāng)有狀態(tài)的對象與外部事件產(chǎn)生互動時,其內(nèi)部狀態(tài)會發(fā)生改變,從而使得其行為也隨之發(fā)生改變。如人的情緒有高興的時候和傷心的時候,不同的情緒有不同的行為,當(dāng)然外界也會影響其情緒變化。

對這種有狀態(tài)的對象編程,傳統(tǒng)的解決方案是:將這些所有可能發(fā)生的情況全都考慮到,然后使用 if-else 語句來做狀態(tài)判斷,再進行不同情況的處理。但當(dāng)對象的狀態(tài)很多時,程序會變得很復(fù)雜。而且增加新的狀態(tài)要添加新的 if-else 語句,這違背了“開閉原則”,不利于程序的擴展。

主要優(yōu)點:

  1. 狀態(tài)模式將與特定狀態(tài)相關(guān)的行為局部化到一個狀態(tài)中,并且將不同狀態(tài)的行為分割開來,滿足“單一職責(zé)原則”。
  2. 減少對象間的相互依賴。將不同的狀態(tài)引入獨立的對象中會使得狀態(tài)轉(zhuǎn)換變得更加明確,且減少對象間的相互依賴。
  3. 有利于程序的擴展。通過定義新的子類很容易地增加新的狀態(tài)和轉(zhuǎn)換。

主要缺點:

  1. 狀態(tài)模式的使用必然會增加系統(tǒng)的類與對象的個數(shù)。
  2. 狀態(tài)模式的結(jié)構(gòu)與實現(xiàn)都較為復(fù)雜,如果使用不當(dāng)會導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。

實現(xiàn):

  1. 環(huán)境角色:也稱為上下文,它定義了客戶感興趣的接口,維護一個當(dāng)前狀態(tài),并將與狀態(tài)相關(guān)的操作委托給當(dāng)前狀態(tài)對象來處理。(Context)
  2. 抽象狀態(tài)角色:定義一個接口,用以封裝環(huán)境對象中的特定狀態(tài)所對應(yīng)的行為。(State)
  3. 具體狀態(tài)角色:實現(xiàn)抽象狀態(tài)所對應(yīng)的行為。(Concrete State)

9.訪問者模式(Visitor)

概述:將用于某穩(wěn)定數(shù)據(jù)結(jié)構(gòu)的不同操作,提取出來為單獨的類。使其在不改變數(shù)據(jù)結(jié)構(gòu)代碼的同時,能夠添加新的行為操作,為其中數(shù)據(jù)節(jié)點能提供多種訪問方式。

它將對數(shù)據(jù)的操作與數(shù)據(jù)結(jié)構(gòu)進行分離,是行為類模式中最復(fù)雜的一種模式。

例如,公園中存在多個景點,也存在多個游客,不同的游客對同一個景點的評價可能不同;醫(yī)院醫(yī)生開的處方單中包含多種藥元素,査看它的劃價員和藥房工作人員對它的處理方式也不同,劃價員根據(jù)處方單上面的藥品名和數(shù)量進行劃價,藥房工作人員根據(jù)處方單的內(nèi)容進行抓藥。

這樣的例子還有很多,例如,電影或電視劇中的人物角色,不同的觀眾對他們的評價也不同;還有顧客在商場購物時放在“購物車”中的商品,顧客主要關(guān)心所選商品的性價比,而收銀員關(guān)心的是商品的價格和數(shù)量。

訪問者(Visitor)模式是一種對象行為型模式。

主要優(yōu)點:

  1. 擴展性好。能夠在不修改對象結(jié)構(gòu)中的元素的情況下,為對象結(jié)構(gòu)中的元素添加新的功能。
  2. 復(fù)用性好??梢酝ㄟ^訪問者來定義整個對象結(jié)構(gòu)通用的功能,從而提高系統(tǒng)的復(fù)用程度。
  3. 靈活性好。訪問者模式將數(shù)據(jù)結(jié)構(gòu)與作用于結(jié)構(gòu)上的操作解耦,使得操作集合可相對自由地演化而不影響系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)。
  4. 符合單一職責(zé)原則。訪問者模式把相關(guān)的行為封裝在一起,構(gòu)成一個訪問者,使每一個訪問者的功能都比較單一。

主要缺點:

  1. 增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類,都要在每一個具體訪問者類中增加相應(yīng)的具體操作,這違背了“開閉原則”。
  2. 破壞封裝。訪問者模式中具體元素對訪問者公布細節(jié),這破壞了對象的封裝性。
  3. 違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。

實現(xiàn):

  1. 抽象訪問者角色:定義一個訪問具體元素的接口,為每個具體元素類對應(yīng)一個訪問操作 visit() ,該操作中的參數(shù)類型標(biāo)識了被訪問的具體元素。(Visitor)
  2. 具體訪問者角色:實現(xiàn)抽象訪問者角色中聲明的各個訪問操作,確定訪問者訪問一個元素時該做什么。(ConcreteVisitor)
  3. 抽象元素角色:聲明一個包含接受操作 accept() 的接口,被接受的訪問者對象作為 accept() 方法的參數(shù)。(Element)
  4. 具體元素角色:實現(xiàn)抽象元素角色提供的 accept() 操作,其方法體通常都是 visitor.visit(this) ,另外具體元素中可能還包含本身業(yè)務(wù)邏輯的相關(guān)操作。(ConcreteElement)
  5. 對象結(jié)構(gòu)角色:是一個包含元素角色的容器,提供讓訪問者對象遍歷容器中的所有元素的方法,通常由 List、Set、Map 等聚合類實現(xiàn)。(Object Structure)

10.中介者模式(Mediator)

概述:定義一個中介類來封裝一些列對象(類)之間的交互,降低對象間的耦合性,且可以獨立改變他們之間的交互。中介者模式又叫調(diào)停模式,它是迪米特法則的典型應(yīng)用。中介者模式是一種對象行為型模式,

在現(xiàn)實生活中,常常會出現(xiàn)好多對象之間存在復(fù)雜的交互關(guān)系,這種交互關(guān)系常常是“網(wǎng)狀結(jié)構(gòu)”,它要求每個對象都必須知道它需要交互的對象。例如,每個人必須記住他(她)所有朋友的電話;而且,朋友中如果有人的電話修改了,他(她)必須告訴其他所有的朋友修改,這叫作“牽一發(fā)而動全身”,非常復(fù)雜。

如果把這種“網(wǎng)狀結(jié)構(gòu)”改為“星形結(jié)構(gòu)”的話,將大大降低它們之間的“耦合性”,這時只要找一個“中介者”就可以了。如前面所說的“每個人必須記住所有朋友電話”的問題,只要在網(wǎng)上建立一個每個朋友都可以訪問的“通信錄”就解決了。這樣的例子還有很多,例如,你剛剛參加工作想租房,可以找“房屋中介”;或者,自己剛剛到一個陌生城市找工作,可以找“人才交流中心”幫忙。

在軟件的開發(fā)過程中,這樣的例子也很多,例如,在 MVC 框架中,控制器(C)就是模型(M)和視圖(V)的中介者;還有大家常用的 QQ 聊天程序的“中介者”是 QQ 服務(wù)器。所有這些,都可以采用“中介者模式”來實現(xiàn),它將大大降低對象之間的耦合性,提高系統(tǒng)的靈活性。

主要優(yōu)點:

  1. 降低了對象之間的耦合性,使得對象易于獨立地被復(fù)用。
  2. 將對象間的一對多關(guān)聯(lián)轉(zhuǎn)變?yōu)橐粚σ坏年P(guān)聯(lián),提高系統(tǒng)的靈活性,使得系統(tǒng)易于維護和擴展。

主要缺點:

當(dāng)同事類太多時,中介者的職責(zé)將很大,它會變得復(fù)雜而龐大,以至于系統(tǒng)難以維護

實現(xiàn):

  1. 抽象中介者角色:它是中介者的接口,提供了同事對象注冊與轉(zhuǎn)發(fā)同事對象信息的抽象方法。(Mediator)
  2. 具體中介者角色:實現(xiàn)中介者接口,定義一個 List 來管理同事對象,協(xié)調(diào)各個同事角色之間的交互關(guān)系,因此它依賴于同事角色。(ConcreteMediator)
  3. 抽象同事類角色:定義同事類的接口,保存中介者對象,提供同事對象交互的抽象方法,實現(xiàn)所有相互影響的同事類的公共功能。(Colleague)
  4. 具體同事類角色:是抽象同事類的實現(xiàn)者,當(dāng)需要與其他同事對象交互時,由中介者對象負(fù)責(zé)后續(xù)的交互。(Concrete Colleague)

11.解釋器模式(Interpreter)

http://c.biancheng.net/view/1402.html

用于面向?qū)ο蟮木幾g解釋器。

解釋器模式.gif
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容