淺談25種設計模式(4/25)(此坑未填)

設計模式彙總

建立型模式

這些設計模式提供了一種在建立對象的同時隱藏建立邏輯的方式,而不是使用新的運算符直接實例化對象。這使得程序在判斷針對某個給定實例須要建立哪些對象時更加靈活。算法

  1. 工廠模式(Factory Pattern)
  2. 抽象工廠模式(Abstract Factory Pattern)
  3. 單例模式(Singleton Pattern)
  4. 建造者模式(Builder Pattern)
  5. 原型模式(Prototype Pattern)

結構型模式

這些設計模式關注類和對象的組合。繼承的概念被用來組合接口和定義組合對象得到新功能的方式。編程

  1. 適配器模式(Adapter Pattern)
  2. 橋接模式(Bridge Pattern)
  3. 過濾器模式(Filter、Criteria Pattern)
  4. 組合模式(Composite Pattern)
  5. 裝飾器模式(Decorator Pattern)
  6. 外觀模式(Facade Pattern)
  7. 享元模式(Flyweight Pattern)
  8. 代理模式(Proxy Pattern)

行爲型模式

這些設計模式特別關注對象之間的通訊。設計模式

  1. 責任鏈模式(Chain of Responsibility Pattern)
  2. 命令模式(Command Pattern)
  3. 解釋器模式(Interpreter Pattern)
  4. 迭代器模式(Iterator Pattern)
  5. 中介者模式(Mediator Pattern)
  6. 備忘錄模式(Memento Pattern)
  7. 觀察者模式(Observer Pattern)
  8. 狀態模式(State Pattern)
  9. 空對象模式(Null Object Pattern)
  10. 策略模式(Strategy Pattern)
  11. 模板模式(Template Pattern)
  12. 訪問者模式(Visitor Pattern)

1 適配器模式

定義

將一個類的接口轉換成客戶但願的另一個接口。Adapter模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠在一塊兒工做。
咱們用圖來形象的解釋這一律念:微信

clipboard.png

clipboard.png

這裏的重點在於,老接口有特殊功能,咱們不忍捨棄,好比只有歐洲的插頭(老接口)能從插座裏得到電,沒有電咱們過不下去。這個功能咱們沒法捨棄
爲了繼續享受這個特殊功能,咱們使用適配器模式,讓咱們手中的美國的插頭(新接口),擁有老接口的能力。ide

本例使用場景

例如一個美國人說英語,一箇中國人說中文,爲了跟美國人作生意,說英文這個功能咱們沒法捨棄,可是咱們是中國人,天生不會說英文。因而二者想要交流,就須要一個適配器,來充當溝通二者的工做。如今,咱們但願讓一個能說中國話的個體(實現說中文的接口的類),開口說英文。函數

角色

  • 目標接口(Target)(中文溝通能力的接口):定義了咱們但願用來承載被適配類特殊功能的方法的接口,好比例子中,咱們但願用中國人的說話方法,承載美國人的speak功能,說話方法就定義在該接口中。
  • 目標類(Target class)(中國人類):咱們所期待的擁有特殊功能的具體類,也就是要說英文的類。
  • 須要適配的類(Adaptee)(美國人類):須要適配的類或適配者類,類中還有咱們還不忍捨棄的功能,咱們須要迂迴實現他
  • 適配器(Adapter)(翻譯類):經過包裝一個須要適配的對象,把原接口轉換成目標接口。

類適配器

適配器有兩種主要的實現,咱們先看第一種——類適配器測試

具體實現

// 被適配類,已存在的、具備還有用處的特殊功能、但不符合咱們既有的標準接口的類 
//——本例中即爲一個會說f**k的美國人(你能夠看做這個美國人實現了說英文的接口,不過這個可有可無,省略),他說的話咱們聽不懂
class American{  
    public void speak() {  
        System.out.println("f**k");  
    }  
}
// 目標接口,或稱爲標準接口  ——這裏是一個說中文能力的接口,他定義了方法「說話」。
interface SpeakChinese {  
    public void shuoHua();  
}
// 具體目標類,只提供普通功能 ——這裏咱們的具體實現是一箇中國人類,他實現了說中國話的接口
class Chinese implements SpeakChinese {  
    public void shuoHua() {  
        System.out.println("敲裏嗎");  
    }  
}
// 適配器類,繼承了被適配類,同時實現標準接口  ——如今咱們以爲,那個美國人說的四字真言好拽哦,我也要學會,因而咱們定義了適配器
class Adapter extends American implements SpeakChinese {  
    public void shuoHua() {  
        super.speak();  
    }  
}

測試

如今咱們定義一個laoWang,老王是一個Chinese,他會說話這個方法。
而後再定義一個適配器,看看適配器能不能用中文的說話方法,說出英文來。ui

// 測試類public class Client {  
    public static void main(String[] args) {  
        // 使用普通功能類  
        SpeakChinese laoWang= new Chinese();  
        laoWang.shuoHua();  
          
        // 使用特殊功能類,即適配類  
        SpeakChinese adapter = new Adapter();  
        adapter.shuoHua();  
    }  
}

測試結果:this

敲裏嗎
f**k

很棒,如今用了適配器,適配器用說中文的方式,說出了這句著名的英文,如今咱們迂迴獲得了說這四個字母的能力,能夠去找外國友人交流感情了。spa

對象適配器

另一種適配器模式是對象適配器,它不是使用多繼承或繼承再實現的方式,而是使用直接關聯,或者稱爲委託的方式。

具體實現

其餘目標類和被適配類都同樣,就是適配器類的定義方式有所不一樣:

// 適配器類,直接關聯被適配類,同時實現標準接口  
class Adapter implements SpeakChinese {  
    // 直接關聯被適配類  
    private American american;  
      
    // 能夠經過構造函數傳入具體須要適配的被適配類對象  
    public Adapter (American american) {  
        this.american = american;  
    }  
      
    public void shuoHua() {  
        // 這裏是使用委託的方式完成特殊功能  
        this.american.speak();  
    }  
}

測試

在這裏,咱們爲了更靈活一點,定義了一個加州人,加州人和外面那些妖豔賤貨不同,他們比較優雅,通常喜歡說hello。

class Californian extends American{  
    public void speak() {  
        System.out.println("hello");  
    }  
}
public class Client {  
    public static void main(String[] args) {  
        // 使用普通功能類  
        SpeakChinese laoWang = new Chinese();  
        laoWang.shuoHua();  
          
        // 使用特殊功能類,即適配類,  
        // 須要先建立一個被適配類的對象做爲參數  
        American tom = new Californian(){}
        Target adapter = new Adapter(tom);  
        adapter.shuoHua();  
    }  
}

測試結果

敲裏嗎
hello

一樣的,咱們用適配器得到了像加州人那樣優雅的說英文的能力。對象適配器相對於類適配器來講比較靈活,咱們能夠複用這個適配器,經過傳參的不一樣,獲得德克薩斯人,弗吉尼亞人,佛羅里達人的說話方式。

優劣

模式總結

優勢

  • 經過適配器,客戶端能夠調用同一接口,於是對客戶端來講是透明的。這樣作更簡單、更直接、更緊湊。
  • 複用了現存的類,解決了現存類和複用環境要求不一致的問題。
  • 將目標類和適配者類解耦,經過引入一個適配器類重用現有的適配者類,而無需修改原有代碼。
  • 一個對象適配器能夠把多個不一樣的適配者類適配到同一個目標,也就是說,同一個適配器能夠把適配者類和它的子類都適配到目標接口。

缺點

  • 過多的使用適配器,會讓系統很是零亂,不易總體進行把握。好比,明明看到調用的是 A 接口,其實內部被適配成了 B 接口的實現,一個系統若是太多出現這種狀況,無異於一場災難。所以若是不是頗有必要,能夠不使用適配器,而是直接對系統進行重構。

2 策略模式

定義

首先咱們理解策略的概念,策略就是一組算法,一種實現。策略模式定義了一系列的算法,並將每個算法封裝起來,並且使他們能夠相互替換,讓算法獨立於使用它的客戶而獨立變化。

本例使用場景

例如足智多謀的諸葛亮,他的每一個錦囊,就是一個策略,如今諸葛亮給了關羽三個錦囊——錦囊A,錦囊B,錦囊C,告訴關羽若是敵軍數量在一萬到三萬之內,打開錦囊A;敵軍數量在三萬到五萬之間,打開錦囊B;還更多的話,打開錦囊C。

角色

  • 環境(Context)(具體策略的執行者——關羽):持有一個Strategy的引用。
  • 抽象策略(Strategy)(錦囊接口或者抽象類):這是一個抽象角色,一般由一個接口或抽象類實現。此角色給出全部的具體策略類所需的接口。
  • 具體策略(ConcreteStrategy)(具體的錦囊類):包裝了相關的算法或行爲。

具體實現

//抽象策略類 錦囊接口
public interface JinNang {
    /**
     * 策略方法 打開錦囊
     */
    public void openJinNang();
}
//具體策略類 錦囊A
public class JinNangA implements JinNang {

    @Override
    public void openJinNang(Integer enermyNum) {
        System.out.println("朝敵軍使用拋擲糞便攻擊,殺敵20%!傷敵數量爲:"+enermyNum*0.2);
    }

}

//具體策略類 錦囊B
public class JinNangB  implements JinNang {

    @Override
    public void openJinNang(Integer enermyNum) {
        System.out.println("朝敵軍播放難忘今宵以瓦解敵軍意志,殺敵50%!傷敵數量爲:"+enermyNum*0.5);
    }

}

//具體策略類 錦囊C
public class JinNangC implements JinNang {

    @Override
    public void openJinNang(Integer enermyNum) {
        System.out.println("丫的還不快跑!?");
    }

}
//環境角色類--關羽
public class GuanYu{
    //持有一個具體策略的對象
    private JinNang jinNang;

    /**
     * 策略方法
     */
    public void fight(Integer enermyNum){
        if (enermyNum >10000&enermyNum<30000){
            jinNang=new JinNangA();
        } else if (enermyNum >30000&enermyNum<50000){
            jinNang=new JinNangB();
        } else{
            jinNang=new JinNangC();
        }
        jinNang.openJinNang(enermyNum);
    }

}

測試

好的,如今咱們的關羽跨上赤兔馬,拎起青龍刀,來到了陣前,對面分別出動了兩個師,四個師,十個師的兵力幹他!即使如此,咱們的小英雄也A了上去!

public static void main(String[] args) {
        GuanYu guanYu = new GuanYu();
        guanYu.fight(20000);
        guanYu.fight(40000);
        guanYu.fight(100000);
    }

測試結果
顯而易見,測試結果是:

朝敵軍使用拋擲糞便攻擊,殺敵20%!傷敵數量爲:4000.0
朝敵軍播放難忘今宵以瓦解敵軍意志,殺敵50%!傷敵數量爲:20000.0
丫的還不快跑!?

模式總結

  • 策略模式的重心不是如何實現算法,而是如何組織、調用這些算法,從而讓程序結構更靈活,具備更好的維護性和擴展性。
  • 運行期間,策略模式在每個時刻只能使用一個具體的策略實現對象,雖然能夠動態地在不一樣的策略實現中切換,可是同時只能使用一個。

優劣

優勢

  • 策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行爲族。恰當使用繼承能夠把公共的代碼移到父類裏面,從而避免代碼重複。
  • 使用策略模式能夠避免使用多重條件(if-else)語句。多重條件語句不易維護,它把採起哪種算法或採起哪種行爲的邏輯與算法或行爲的邏輯混合在一塊兒,通通列在一個多重條件語句裏面,比使用繼承的辦法還要原始和落後。

缺點

  • 客戶端必須知道全部的策略類,並自行決定使用哪個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道算法或行爲的狀況。
  • 因爲策略模式把每一個具體的策略實現都單獨封裝成爲類,若是備選的策略不少的話,那麼對象的數目就會很可觀。

3 外觀模式

定義

外觀模式(Facade Pattern)又稱爲門面模式,它爲系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得子系統更加容易使用。該模式能夠隱藏系統的複雜性,提供了客戶端請求的簡化方法和對現有系統類方法的委託調用。

本例使用場景

蜀漢集團總經理諸葛亮爲了光復中原,推出了「三個臭皮匠」陣法,由關羽張飛趙雲壓陣,在砍人的時候充當蜀軍的門面。因而在羣P的時候,對於他們的客戶(敵人)來講,和外觀(陣法)交互(打架)並不須要知道他們內在的細節,許多繁瑣的邏輯,已經被門面封裝了。

角色

  • 門面(facade)角色(三個臭皮匠陣法):外觀模式的核心。它被客戶角色調用,它熟悉子系統的功能。內部根據客戶角色的需求預約了幾種功能的組合。
  • 子系統(Subsystem)角色(關張趙三個子系統):子系統類,實現子系統的功能,處理外觀類指派的任務,注意子系統類不含有外觀類的引用。

具體實現

咱們先來定義三個子系統:關張趙

/**
 * 子系統關羽
 */
public class GuanYu {
    //剪刀
    public void jianDao(){
        System.out.println("關羽出剪刀");
    }
    public void shiTou(){
        System.out.println("關羽出石頭");
    }
    public void bu(){
        System.out.println("關羽出布");
    }
}
/**
 * 子系統趙雲
 */
public class ZhaoYun{
    //剪刀
    public void jianDao(){
        System.out.println("趙雲出剪刀");
    }
    public void shiTou(){
        System.out.println("趙雲出石頭");
    }
    public void bu(){
        System.out.println("趙雲出布");
    }
}
/**
 * 子系統張飛
 */
public class ZhangFei {
    //剪刀
    public void jianDao(){
        System.out.println("張飛出剪刀");
    }
    public void shiTou(){
        System.out.println("張飛出石頭");
    }
    public void bu(){
        System.out.println("張飛出布");
    }
}

接下來定義統一的外觀類——三個臭皮匠陣法,這個陣法有三個絕技,青龍騰,白龍騰和黑龍騰,至於技能內到底怎麼實現的,大家這些凡人就不要在乎了,總之發動起來,天上都是龍,大家只要負責喊666就能夠了。

public class ThreeChouPiJiang{
    private GuanYu guanYu;
    private ZhangFei zhangFei;
    private ZhaoYun zhaoYun;
    ThreeChouPiJiang(){
        guanYu =new GuanYu();
        zhangFei = new ZhangFei();
        zhaoYun = new ZhaoYun();
    }
    //青龍騰
    public void qingLongTeng(){
        zhangFei.bu();
        zhaoYun.bu();
        guanYu.shiTou();
        System.out.println("青龍騰:關羽輸了,關羽出去砍人;");
        System.out.println("BO~BO~BO~經費燃燒中~ =============");
    }
    //黑龍騰
    public void heiLongTeng(){
        guanYu.bu();
        zhaoYun.bu();
        zhangFei.shiTou();
        System.out.println("黑龍騰:張飛輸了,張飛出去砍人;");
        System.out.println("BO~BO~BO~經費燃燒中~ =============");
    }
    //白龍騰
    public void baiLongTeng(){
        guanYu.bu();
        zhangFei.bu();
        zhaoYun.shiTou();
        System.out.println(":趙雲輸了,趙雲出去砍人;");
        System.out.println("BO~BO~BO~經費燃燒中~ =============");
    }
}

測試

好了,咱們的陣法已經定義好了,如今諸葛亮意氣風發,決定要北伐中原,咱們的三個臭皮匠陣法,開始發揮威力:

public static void main(String[] args) {
    ThreeChouPiJiang threeChouPiJiang = new ThreeChouPiJiang();
    ThreeChouPiJiang threeChouPiJiang = new ThreeChouPiJiang();
    threeChouPiJiang.baiLongTeng();
    threeChouPiJiang.qingLongTeng();
    threeChouPiJiang.heiLongTeng();
}

測試結果:

關羽出布
張飛出布
趙雲出石頭
白龍騰:趙雲輸了,趙雲出去砍人;
BO~BO~BO~經費燃燒中~ =============
張飛出布
趙雲出布
關羽出石頭
青龍騰:關羽輸了,關羽出去砍人;
BO~BO~BO~經費燃燒中~ =============
關羽出布
趙雲出布
張飛出石頭
黑龍騰:張飛輸了,張飛出去砍人;
BO~BO~BO~經費燃燒中~ =============

威力果真是十分驚人啊!對於敵人而言,他們只知道三個臭皮匠陣法使用了絕招,根本不會知道絕招內部竟然是這三個貨用剪刀石頭布搞出來的。在頂級特效的加持下,這個門面仍是十分整潔十分威風十分唬人的。

模式總結

外觀模式的目的不是給予子系統添加新的功能接口,而是爲了讓外部減小與子系統內多個模塊的交互,鬆散耦合,從而讓外部可以更簡單地使用子系統。
外觀模式的本質是:封裝交互,簡化調用。

優劣

優勢

  • 鬆散耦合,使得客戶端和子系統之間解耦,讓子系統內部的模塊功能更容易擴展和維護;
  • 簡單易用,客戶端根本不須要知道子系統內部的實現,或者根本不須要知道子系統內部的構成,它只須要跟Facade類交互便可。
  • 更好的劃分訪問層次,有些方法是對系統外的,有些方法是系統內部相互交互的使用的。子系統把那些暴露給外部的功能集中到門面中,這樣就能夠實現客戶端的使用,很好的隱藏了子系統內部的細節。

缺點

  • 在不引入抽象外觀類的狀況下,增長新的子系統可能須要修改外觀類或客戶端的源代碼,違背了「開閉原則」

4 觀察者模式

定義

在對象之間定義了一對多的依賴,這樣一來,當一個對象改變狀態,依賴它的對象會收到通知並自動更新。
簡單來講,其實就是發佈訂閱模式,發佈者發佈信息,訂閱者獲取信息,訂閱了就能收到信息,沒訂閱就收不到信息。

本例使用場景

例如微信公衆號服務,不定時發佈一些消息,關注公衆號就能夠收到推送消息,取消關注就收不到推送消息。

角色

  • 抽象被觀察者(公衆號接口):也就是一個抽象主題,它把全部對觀察者對象的引用保存在一個集合中,每一個主題均可以有任意數量的觀察者。抽象主題提供一個接口,能夠增長和刪除觀察者角色。通常用一個抽象類和接口來實現。
  • 抽象觀察者(訂閱人接口):爲全部的具體觀察者定義一個接口,在獲得主題通知時更新本身。
  • 具體被觀察者(公衆號):也就是一個具體的主題,在集體主題的內部狀態改變時,全部登記過的觀察者發出通知。
  • 具體觀察者(訂閱人):實現抽象觀察者角色所須要的更新接口,一邊使自己的狀態與製圖的狀態相協調。

具體實現

/***
 * 抽象被觀察者接口
 * 聲明瞭添加、刪除、通知觀察者方法
 */
public interface Observerable {
    
    public void registerObserver(Observer o);//新增訂閱人
    public void removeObserver(Observer o);//刪除訂閱人
    public void notifyObserver();//發佈消息
    
}
/***
 * 抽象觀察者
 * 定義了一個update()方法,當被觀察者調用notifyObservers()方法時,觀察者的update()方法會被回調。
 */
public interface Observer {
    public void update(String message);//更新消息
}
/**
 * 被觀察者,也就是微信公衆號服務
 * 實現了Observerable接口,對Observerable接口的三個方法進行了具體實現
 */
public class WechatServer implements Observerable {
    //注意到這個List集合的泛型參數爲Observer接口,設計原則:面向接口編程而不是面向實現編程
    private List<Observer> list;
    private String message;
    
    public WechatServer() {
        list = new ArrayList<Observer>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        
        list.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }
    
    //遍歷通知
    @Override
    public void notifyObserver() {
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }
    
    public void setInfomation(String s) {
        this.message = s;
        System.out.println("微信服務更新消息: " + s);
        //消息更新,通知全部觀察者
        notifyObserver();
    }
}
/**
 * 觀察者
 * 實現了update方法
 */
public class User implements Observer {

    private String name;
    private String message;
    
    public User(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        this.message = message;
        read();
    }
    
    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }
    
}

測試

首先註冊了三個用戶,ZhangSan、LiSi、WangWu。公衆號發佈了一條消息"PHP是世界上最好用的語言!",三個用戶都收到了消息。

用戶ZhangSan看到消息後頗爲震驚,果斷取消訂閱,這時公衆號又推送了一條消息,此時用戶ZhangSan已經收不到消息,其餘用戶

仍是正常能收到推送消息。

public class Test {
    
    public static void main(String[] args) {
        WechatServer server = new WechatServer();
        
        Observer userZhang = new User("ZhangSan");
        Observer userLi = new User("LiSi");
        Observer userWang = new User("WangWu");
        
        server.registerObserver(userZhang);
        server.registerObserver(userLi);
        server.registerObserver(userWang);
        server.setInfomation("PHP是世界上最好用的語言!");
        
        System.out.println("----------------------------------------------");
        server.removeObserver(userZhang);
        server.setInfomation("JAVA是世界上最好用的語言!");
        
    }
}

測試結果:
clipboard.png

5 責任鏈模式

定義

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

爲完成同一個請求,若是存在多個請求處理器以及未知請求處理器個數或者請求處理器可動態配置的狀況下,能夠考慮使用責任鏈模式。

適用於: 鏈條式處理事情。工做流程化、消息處理流程化、事物流程化;

本例使用場景

聖鬥士星矢,五小強們勇闖黃金十二宮,咱們能夠把這十二宮,當作是十二個處理者,他們用一條鏈串起來。

角色

  • Handler抽象處理者(黃金聖鬥士): 定義一個處理請求的接口,提供對後續處理者的引用
  • ConcreteHandler具體處理者(如白羊座聖鬥士): 抽象處理者的子類,處理用戶請求,可選將請求處理掉仍是傳給下家;在具體處理者中能夠訪問鏈中下一個對象,以便請求的轉發。

具體實現

咱們先來定義一個抽象的黃金聖鬥士的抽象類:

public interface GoldenWarrior {
    void fight(String xiaoQiangName,String response,GoldenWarriorChain chain);
}

咱們定義一個白羊座聖鬥士:

public class AriesWorrior implements GoldenWarrior{
    @Override
    public void fight(String request, String response, GoldenWarriorChain chain) {

        System.out.println(request+"fight with AriesWorrior,AriesWorrior lose");

        chain.fight(request, response, chain);

        System.out.println(response+" reback to AriesWorrior here!");
    }
}

再來定義一個獅子座聖鬥士

public class LeoWorrior implements GoldenWarrior{
    @Override
    public void fight(String request, String response, GoldenWarriorChain chain) {

        System.out.println(request+"fight with LeoWorrior,LeoWorrior lose");

        chain.fight(request, response, chain);

        System.out.println(response+" reback to LeoWorrior here!");
    }
}

而後,是咱們的責任鏈對象,或者說是咱們例子裏面的 十二宮(其實咱們就實現了兩宮)對象

public class GoldenWarriorChain implements GoldenWarrior{
    //十二宮的聖鬥士們
    private List<GoldenWarrior> goldenWarriors=new ArrayList<GoldenWarrior>();
    //目前到哪一個宮了
    private int index;

    public GoldenWarriorChain addWorrior(GoldenWarrior warrior){
        this.goldenWarriors.add(warrior);
        return this;
    }

    public void fight(String request, String response,GoldenWarriorChain chain) {

        if(index==goldenWarriors.size())
            return;//若是鏈條裏沒有filter或是鏈條裏的filter都調用過了(有點象遞歸)

        goldenWarriors.get(index++).fight(request, response, chain);
    }
}

測試

public static void  main(String[] a){
        GoldenWarriorChain goldenWarriorChain = new GoldenWarriorChain();
        goldenWarriorChain.addWorrior(new LeoWorrior());
        goldenWarriorChain.addWorrior(new AriesWorrior());

        goldenWarriorChain.fight("星矢","",goldenWarriorChain);
    }

結果

星矢fight with LeoWorrior,LeoWorrior lose
星矢fight with AriesWorrior,AriesWorrior lose
reback to AriesWorrior here!
reback to LeoWorrior here!

由於String是不可變對象,故而,response和request沒能在調用後被自動傳遞至下一層,或者遞歸後被自動帶回上一層(實際上咱們也沒有對它進行過處理,只是打印出來而已),若是response和request是對象的話,上層對象就能獲得下層的結果,不過咱們的核心在不在這,無足輕重。

優缺點

優勢:

1。責任的分擔。每一個類只須要處理本身該處理的工做(不應處理的傳遞給下一個對象完成),明確各種的責任範圍,符合類的最小封裝原則。
2。能夠根據須要自由組合工做流程。如工做流程發生變化,能夠經過從新分配對象鏈即可適應新的工做流程。
3。類與類之間能夠以鬆耦合的形式加以組織。

缺點:

由於處理時以鏈的形式在對象間傳遞消息,根據實現方式不一樣,有可能會影響處理的速度。

相關文章
相關標籤/搜索