C++設(shè)計(jì)模式 | 四種行為型模式——模版方法模式亡哄、策略模式枝缔、命令模式、觀察者模式

模版方法模式

定義一個(gè)操作中算法的框架,而將一些步驟延遲到子類中愿卸。模板方法模式使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

AbstractClass(抽象類):在抽象類中定義了一系列基本操作趴荸,這些基本操作可以是具體的儒溉,也可以是抽象的,每一個(gè)基本操作對(duì)應(yīng)算法的一個(gè)步驟发钝,在其子類中可以重定義或?qū)崿F(xiàn)這些步驟顿涣。同時(shí),在抽象類中實(shí)現(xiàn)了一個(gè)模板方法(Template Method)酝豪,用于定義一個(gè)算法的框架园骆,模板方法不僅可以調(diào)用在抽象類中實(shí)現(xiàn)的基本方法,也可以調(diào)用在抽象類的子類中實(shí)現(xiàn)的基本方法寓调,還可以調(diào)用其他對(duì)象中的方法锌唾。

ConcreteClass(具體子類):它是抽象類的子類,用于實(shí)現(xiàn)在父類中聲明的抽象基本操作以完成子類特定算法的步驟夺英,也可以覆蓋在父類中已經(jīng)實(shí)現(xiàn)的具體基本操作晌涕。

#include<iostream>
using namespace std;


class DrinkTemplate{
public:
    //煮水
    virtual void BoildWater() = 0;
    //沖泡
    virtual void Brew() = 0;
    //倒入杯中
    virtual void PourInCup() = 0;
    //加輔助料
    virtual void AddSomething() = 0;

    //模板方法
    void Make(){
        BoildWater();
        Brew();
        PourInCup();
        AddSomething();
    }
};

//沖泡咖啡
class Coffee : public DrinkTemplate{
public:
    virtual void BoildWater(){
        cout << "煮山泉水..." << endl;
    }
    //沖泡
    virtual void Brew(){
        cout << "沖泡咖啡..." << endl;
    }
    //倒入杯中
    virtual void PourInCup(){
        cout << "咖啡倒入杯中..." << endl;
    }
    //加輔助料
    virtual void AddSomething(){
        cout << "加糖,加牛奶,加點(diǎn)醋..." << endl;
    }
};

//沖泡茶水
class Tea : public DrinkTemplate{
public:
    virtual void BoildWater(){
        cout << "煮自來(lái)水..." << endl;
    }
    //沖泡
    virtual void Brew(){
        cout << "沖泡鐵觀音..." << endl;
    }
    //倒入杯中
    virtual void PourInCup(){
        cout << "茶水倒入杯中..." << endl;
    }
    //加輔助料
    virtual void AddSomething(){
        cout << "加糖..加檸檬...加生姜..." << endl;
    }
};

void test01(){

    Tea* tea = new Tea;
    tea->Make();

    cout << "-----------" << endl;

    Coffee* coffee = new Coffee;
    coffee->Make();
    
}


int main(){

    test01();

    return 0;
}
模板方法的優(yōu)缺點(diǎn)及適用場(chǎng)景

優(yōu)點(diǎn):
(1)在父類中形式化地定義一個(gè)算法痛悯,而由它的子類來(lái)實(shí)現(xiàn)細(xì)節(jié)的處理余黎,在子類實(shí)現(xiàn)詳細(xì)的處理算法時(shí)并不會(huì)改變算法中步驟的執(zhí)行次序。
(2)模板方法模式是一種代碼復(fù)用技術(shù)载萌,它在類庫(kù)設(shè)計(jì)中尤為重要惧财,它提取了類庫(kù)中的公共行為,將公共行為放在父類中扭仁,而通過(guò)其子類來(lái)實(shí)現(xiàn)不同的行為垮衷,它鼓勵(lì)我們恰當(dāng)使用繼承來(lái)實(shí)現(xiàn)代碼復(fù)用。
(3)可實(shí)現(xiàn)一種反向控制結(jié)構(gòu)乖坠,通過(guò)子類覆蓋父類的鉤子方法來(lái)決定某一特定步驟是否需要執(zhí)行搀突。
(4)在模板方法模式中可以通過(guò)子類來(lái)覆蓋父類的基本方法,不同的子類可以提供基本方法的不同實(shí)現(xiàn)熊泵,更換和增加新的子類很方便仰迁,符合單一職責(zé)原則和開閉原則。

缺點(diǎn):
需要為每一個(gè)基本方法的不同實(shí)現(xiàn)提供一個(gè)子類顽分,如果父類中可變的基本方法太多徐许,將會(huì)導(dǎo)致類的個(gè)數(shù)增加,系統(tǒng)更加龐大卒蘸,設(shè)計(jì)也更加抽象犁功。

適用場(chǎng)景:
(1)具有統(tǒng)一的操作步驟或操作過(guò)程;
(2) 具有不同的操作細(xì)節(jié);
(3) 存在多個(gè)具有同樣操作步驟的應(yīng)用場(chǎng)景实檀,但某些具體的操作細(xì)節(jié)卻各不相同;

在抽象類中統(tǒng)一操作步驟霉旗,并規(guī)定好接口;讓子類實(shí)現(xiàn)接口冰蘑。這樣可以把各個(gè)具體的子類和操作步驟解耦合和泌。

策略模式

策略模式定義了一系列的算法村缸,并將每一個(gè)算法封裝起來(lái),而且使它們還可以相互替換武氓。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化梯皿。

Context(環(huán)境類):環(huán)境類是使用算法的角色,它在解決某個(gè)問(wèn)題(即實(shí)現(xiàn)某個(gè)方法)時(shí)可以采用多種策略县恕。在環(huán)境類中維持一個(gè)對(duì)抽象策略類的引用實(shí)例东羹,用于定義所采用的策略。
Strategy(抽象策略類):它為所支持的算法聲明了抽象方法忠烛,是所有策略類的父類属提,它可以是抽象類或具體類,也可以是接口美尸。環(huán)境類通過(guò)抽象策略類中聲明的方法在運(yùn)行時(shí)調(diào)用具體策略類中實(shí)現(xiàn)的算法冤议。
ConcreteStrategy(具體策略類):它實(shí)現(xiàn)了在抽象策略類中聲明的算法,在運(yùn)行時(shí)师坎,具體策略類將覆蓋在環(huán)境類中定義的抽象策略類對(duì)象恕酸,使用一種具體的算法實(shí)現(xiàn)某個(gè)業(yè)務(wù)處理。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;


//抽象武器 武器策略
class WeaponStrategy{
public:
    virtual void UseWeapon() = 0;
};

class Knife : public WeaponStrategy{
public:
    virtual void UseWeapon(){
        cout << "使用匕首胯陋!" << endl;
    }
};

class AK47 :public WeaponStrategy{
public:
    virtual void UseWeapon(){
        cout << "使用AK47蕊温!" << endl;
    }
};

class Character {
public:
    void setWeapon(WeaponStrategy* weapon){
        this->pWeapon = weapon;
    }
    void ThrowWeapon(){
        this->pWeapon->UseWeapon();
    }
public:
    WeaponStrategy* pWeapon;
};


void test01(){
    
    //創(chuàng)建角色
    Character* character = new Character;

    //武器策略
    WeaponStrategy* knife = new Knife;
    WeaponStrategy* ak47 = new AK47;

    character->setWeapon(knife);
    character->ThrowWeapon();

    character->setWeapon(ak47);
    character->ThrowWeapon();

    delete ak47;
    delete knife;
    delete character;
}

int main(void){

    test01();
    
    return 0;
}
策略模式的優(yōu)缺點(diǎn)及適用場(chǎng)景

優(yōu)點(diǎn):
(1)策略模式提供了對(duì)“開閉原則”的完美支持,用戶可以在不修改原有系統(tǒng)的基礎(chǔ)上選擇算法或行為遏乔,也可以靈活地增加新的算法或行為义矛。
(2)使用策略模式可以避免多重條件選擇語(yǔ)句。多重條件選擇語(yǔ)句不易維護(hù)盟萨,它把采取哪一種算法或行為的邏輯與算法或行為本身的實(shí)現(xiàn)邏輯混合在一起症革,將它們?nèi)坑簿幋a(Hard Coding)在一個(gè)龐大的多重條件選擇語(yǔ)句中,比直接繼承環(huán)境類的辦法還要原始和落后鸯旁。
(3)策略模式提供了一種算法的復(fù)用機(jī)制噪矛。由于將算法單獨(dú)提取出來(lái)封裝在策略類中,因此不同的環(huán)境類可以方便地復(fù)用這些策略類铺罢。

缺點(diǎn):
(1)客戶端必須知道所有的策略類艇挨,并自行決定使用哪一個(gè)策略類。這就意味著客戶端必須理解這些算法的區(qū)別韭赘,以便適時(shí)選擇恰當(dāng)?shù)乃惴ㄋ醣酢Q言之,策略模式只適用于客戶端知道所有的算法或行為的情況。
(2)策略模式將造成系統(tǒng)產(chǎn)生很多具體策略類脉漏,任何細(xì)小的變化都將導(dǎo)致系統(tǒng)要增加一個(gè)新的具體策略類苞冯。

適用場(chǎng)景:
準(zhǔn)備一組算法,并將每一個(gè)算法封裝起來(lái)侧巨,使得它們可以互換舅锄。

命令模式

    將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而讓我們可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化司忱;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志皇忿,以及支持可撤銷的操作。命令模式是一種對(duì)象行為型模式坦仍,其別名為動(dòng)作(Action)模式或事務(wù)(Transaction)模式鳍烁。
命令模式可以將請(qǐng)求發(fā)送者和接收者完全解耦,發(fā)送者與接收者之間沒有直接引用關(guān)系繁扎,發(fā)送請(qǐng)求的對(duì)象只需要知道如何發(fā)送請(qǐng)求幔荒,而不必知道如何完成請(qǐng)求。

Command(抽象命令類):抽象命令類一般是一個(gè)抽象類或接口梳玫,在其中聲明了用于執(zhí)行請(qǐng)求的execute()等方法爹梁,通過(guò)這些方法可以調(diào)用請(qǐng)求接收者的相關(guān)操作。

ConcreteCommand(具體命令類):具體命令類是抽象命令類的子類汽纠,實(shí)現(xiàn)了在抽象命令類中聲明的方法卫键,它對(duì)應(yīng)具體的接收者對(duì)象,將接收者對(duì)象的動(dòng)作綁定其中虱朵。在實(shí)現(xiàn)execute()方法時(shí)莉炉,將調(diào)用接收者對(duì)象的相關(guān)操作(Action)。

Invoker(調(diào)用者):調(diào)用者即請(qǐng)求發(fā)送者碴犬,它通過(guò)命令對(duì)象來(lái)執(zhí)行請(qǐng)求絮宁。一個(gè)調(diào)用者并不需要在設(shè)計(jì)時(shí)確定其接收者,因此它只與抽象命令類之間存在關(guān)聯(lián)關(guān)系服协。在程序運(yùn)行時(shí)可以將一個(gè)具體命令對(duì)象注入其中绍昂,再調(diào)用具體命令對(duì)象的execute()方法,從而實(shí)現(xiàn)間接調(diào)用請(qǐng)求接收者的相關(guān)操作偿荷。

Receiver(接收者):接收者執(zhí)行與請(qǐng)求相關(guān)的操作窘游,它具體實(shí)現(xiàn)對(duì)請(qǐng)求的業(yè)務(wù)處理。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<queue>

using namespace std;


//協(xié)議處理類
class HandleClientProtocol{
public:
    //處理增加金幣
    void AddMoney(){
        cout << "給玩家增加金幣跳纳!" << endl;
    }

    //處理增加鉆石
    void AddDiamond(){
        cout << "給玩家增加鉆石!" << endl;
    }

    //處理玩家裝備
    void AddEquipment(){
        cout << "給玩家穿裝備忍饰!" << endl;
    }

    //處理玩家升級(jí)
    void addLevel(){
        cout << "給玩家升級(jí)!" << endl;
    }
};

//命令接口
class AbstractCommand{
public:
    virtual void handle() = 0; //處理客戶端請(qǐng)求的接口
};


//處理增加金幣請(qǐng)求
class AddMoneyCommand :public AbstractCommand{
public:
    AddMoneyCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->AddMoney();
    }
public:
    HandleClientProtocol* pProtocol;
};

//處理增加鉆石的請(qǐng)求
class AddDiamondCommand :public AbstractCommand{
public:
    AddDiamondCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->AddDiamond();
    }
public:
    HandleClientProtocol* pProtocol;
};


//處理玩家穿裝備的請(qǐng)求
class AddEquipmentCommand : public AbstractCommand{
public:
    AddEquipmentCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->AddEquipment();
    }
public:
    HandleClientProtocol* pProtocol;
};

//處理玩家升級(jí)的請(qǐng)求
class AddLevelCommand : public AbstractCommand{
public:
    AddLevelCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->addLevel();
    }
public:
    HandleClientProtocol* pProtocol;

};


//服務(wù)器程序
class Serser{
public:
    void addRequest(AbstractCommand* command){
        mCommands.push(command);
    }

    void startHandle(){
        while (!mCommands.empty()){

            AbstractCommand* command = mCommands.front();
            command->handle();
            mCommands.pop();
        }
    }
public:
    queue<AbstractCommand*> mCommands;
};

void test01(){
    
    HandleClientProtocol* protocol = new HandleClientProtocol;
    //客戶端增加金幣的請(qǐng)求
    AbstractCommand* addmoney = new AddMoneyCommand(protocol);
    //客戶端增加鉆石的請(qǐng)求
    AbstractCommand* adddiamond = new AddDiamondCommand(protocol);
    //客戶端穿裝備的請(qǐng)求
    AbstractCommand* addequpment = new AddEquipmentCommand(protocol);
    //客戶端升級(jí)請(qǐng)求
    AbstractCommand* addlevel = new AddLevelCommand(protocol);

    Serser* server = new Serser;
    //將客戶端請(qǐng)求加入到處理的隊(duì)列中
    server->addRequest(addmoney);
    server->addRequest(adddiamond);
    server->addRequest(addequpment);
    server->addRequest(addlevel);

    //服務(wù)器開始處理請(qǐng)求
    server->startHandle();
}

int main(void){
    test01();
    return 0;
}
命令模式的優(yōu)缺點(diǎn)及適用場(chǎng)景

優(yōu)點(diǎn):
(1)降低系統(tǒng)的耦合度。由于請(qǐng)求者與接收者之間不存在直接引用寺庄,因此請(qǐng)求者與接收者之間實(shí)現(xiàn)完全解耦艾蓝,相同的請(qǐng)求者可以對(duì)應(yīng)不同的接收者力崇,同樣,相同的接收者也可以供不同的請(qǐng)求者使用赢织,兩者之間具有良好的獨(dú)立性亮靴。
(2)新的命令可以很容易地加入到系統(tǒng)中。由于增加新的具體命令類不會(huì)影響到其他類于置,因此增加新的具體命令類很容易茧吊,無(wú)須修改原有系統(tǒng)源代碼,甚至客戶類代碼俱两,滿足“開閉原則”的要求饱狂。
(3)可以比較容易地設(shè)計(jì)一個(gè)命令隊(duì)列或宏命令(組合命令)曹步。

缺點(diǎn):
使用命令模式可能會(huì)導(dǎo)致某些系統(tǒng)有過(guò)多的具體命令類宪彩。因?yàn)獒槍?duì)每一個(gè)對(duì)請(qǐng)求接收者的調(diào)用操作都需要設(shè)計(jì)一個(gè)具體命令類,因此在某些系統(tǒng)中可能需要提供大量的具體命令類讲婚,這將影響命令模式的使用尿孔。

適用場(chǎng)景:
(1) 系統(tǒng)需要將請(qǐng)求調(diào)用者和請(qǐng)求接收者解耦,使得調(diào)用者和接收者不直接交互筹麸。請(qǐng)求調(diào)用者無(wú)須知道接收者的存在活合,也無(wú)須知道接收者是誰(shuí),接收者也無(wú)須關(guān)心何時(shí)被調(diào)用物赶。
(2) 系統(tǒng)需要在不同的時(shí)間指定請(qǐng)求白指、將請(qǐng)求排隊(duì)和執(zhí)行請(qǐng)求。一個(gè)命令對(duì)象和請(qǐng)求的初始調(diào)用者可以有不同的生命期酵紫,換言之告嘲,最初的請(qǐng)求發(fā)出者可能已經(jīng)不在了,而命令對(duì)象本身仍然是活動(dòng)的奖地,可以通過(guò)該命令對(duì)象去調(diào)用請(qǐng)求接收者橄唬,而無(wú)須關(guān)心請(qǐng)求調(diào)用者的存在性,可以通過(guò)請(qǐng)求日志文件等機(jī)制來(lái)具體實(shí)現(xiàn)参歹。
(3) 系統(tǒng)需要將一組操作組合在一起形成宏命令仰楚。

觀察者模式

觀察者模式是用于建立一種對(duì)象與對(duì)象之間的依賴關(guān)系,一個(gè)對(duì)象發(fā)生改變時(shí)將自動(dòng)通知其他對(duì)象犬庇,其他對(duì)象將相應(yīng)作出反應(yīng)僧界。在觀察者模式中,發(fā)生改變的對(duì)象稱為觀察目標(biāo)臭挽,而被通知的對(duì)象稱為觀察者捂襟,一個(gè)觀察目標(biāo)可以對(duì)應(yīng)多個(gè)觀察者,而且這些觀察者之間可以沒有任何相互聯(lián)系埋哟,可以根據(jù)需要增加和刪除觀察者笆豁,使得系統(tǒng)更易于擴(kuò)展郎汪。

Subject(被觀察者或目標(biāo),抽象主題):被觀察的對(duì)象闯狱。當(dāng)需要被觀察的狀態(tài)發(fā)生變化時(shí)煞赢,需要通知隊(duì)列中所有觀察者對(duì)象。Subject需要維持(添加哄孤,刪除照筑,通知)一個(gè)觀察者對(duì)象的隊(duì)列列表。
ConcreteSubject(具體被觀察者或目標(biāo)瘦陈,具體主題):被觀察者的具體實(shí)現(xiàn)凝危。包含一些基本的屬性狀態(tài)及其他操作。
Observer(觀察者):接口或抽象類晨逝。當(dāng)Subject的狀態(tài)發(fā)生變化時(shí)蛾默,Observer對(duì)象將通過(guò)一個(gè)callback函數(shù)得到通知。
ConcreteObserver(具體觀察者):觀察者的具體實(shí)現(xiàn)捉貌。得到通知后將完成一些具體的業(yè)務(wù)邏輯處理支鸡。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<list>
using namespace std;

//抽象的英雄 抽象的觀察者
class AbstractHero{
public:
    virtual void Update() = 0;
};


//具體英雄  具體觀察者
class HeroA :public AbstractHero{
public:
    HeroA(){
        cout << "英雄A正在擼BOSS ..." << endl;
    }
    virtual void Update(){
        cout << "英雄A停止擼,待機(jī)狀態(tài)..." << endl;
    }
};

class HeroB :public AbstractHero{
public:
    HeroB(){
        cout << "英雄B正在擼BOSS ..." << endl;
    }
    virtual void Update(){
        cout << "英雄B停止擼,待機(jī)狀態(tài)..." << endl;
    }
};

class HeroC :public AbstractHero{
public:
    HeroC(){
        cout << "英雄C正在擼BOSS ..." << endl;
    }
    virtual void Update(){
        cout << "英雄C停止擼,待機(jī)狀態(tài)..." << endl;
    }
};

class HeroD :public AbstractHero{
public:
    HeroD(){
        cout << "英雄D正在擼BOSS ..." << endl;
    }
    virtual void Update(){
        cout << "英雄D停止擼,待機(jī)狀態(tài)..." << endl;
    }
};

class HeroE :public AbstractHero{
public:
    HeroE(){
        cout << "英雄E正在擼BOSS ..." << endl;
    }
    virtual void Update(){
        cout << "英雄E停止擼,待機(jī)狀態(tài)..." << endl;
    }
};


//觀察目標(biāo)抽象
class AbstractBoss{
public:
    //添加觀察者
    virtual void addHero(AbstractHero* hero) = 0;
    //刪除觀察者
    virtual void deleteHero(AbstractHero* hero) = 0;
    //通知所有觀察者
    virtual void notify() = 0; 
};


//具體的觀察者 BOSSA
class BOSSA : public AbstractBoss{
public:
    virtual void addHero(AbstractHero* hero){
        pHeroList.push_back(hero);
    }
    //刪除觀察者
    virtual void deleteHero(AbstractHero* hero){
        pHeroList.remove(hero);
    }
    //通知所有觀察者
    virtual void notify(){
        for (list<AbstractHero*>::iterator it = pHeroList.begin(); it != pHeroList.end();it ++){
            (*it)->Update();
        }
    }
public:
    list<AbstractHero*> pHeroList;
};



void test01(){
    

    //創(chuàng)建觀察者
    AbstractHero* heroA = new HeroA;
    AbstractHero* heroB = new HeroB;
    AbstractHero* heroC = new HeroC;
    AbstractHero* heroD = new HeroD;
    AbstractHero* heroE = new HeroE;

    //創(chuàng)建觀察目標(biāo)
    AbstractBoss* bossA = new BOSSA;
    bossA->addHero(heroA);
    bossA->addHero(heroB);
    bossA->addHero(heroC);
    bossA->addHero(heroD);
    bossA->addHero(heroE);


    cout << "heroC陣亡..." << endl;
    bossA->deleteHero(heroC);

    cout << "Boss死了...通知其他英雄停止攻擊,搶裝備..." << endl;
    bossA->notify();

}


int main(void){
    test01();
    return 0;
}
觀察者模式的優(yōu)缺點(diǎn)及適用場(chǎng)景

優(yōu)點(diǎn):
(1)觀察者模式可以實(shí)現(xiàn)表示層和數(shù)據(jù)邏輯層的分離趁窃,定義了穩(wěn)定的消息更新傳遞機(jī)制牧挣,并抽象了更新接口,使得可以有各種各樣不同的表示層充當(dāng)具體觀察者角色醒陆。
(2)觀察者模式在觀察目標(biāo)和觀察者之間建立一個(gè)抽象的耦合瀑构。觀察目標(biāo)只需要維持一個(gè)抽象觀察者的集合,無(wú)須了解其具體觀察者刨摩。由于觀察目標(biāo)和觀察者沒有緊密地耦合在一起寺晌,因此它們可以屬于不同的抽象化層次。
(3)觀察者模式支持廣播通信码邻,觀察目標(biāo)會(huì)向所有已注冊(cè)的觀察者對(duì)象發(fā)送通知折剃,簡(jiǎn)化了一對(duì)多系統(tǒng)設(shè)計(jì)的難度。
(4)觀察者模式滿足“開閉原則”的要求像屋,增加新的具體觀察者無(wú)須修改原有系統(tǒng)代碼怕犁,在具體觀察者與觀察目標(biāo)之間不存在關(guān)聯(lián)關(guān)系的情況下,增加新的觀察目標(biāo)也很方便己莺。

缺點(diǎn):
(1)如果一個(gè)觀察目標(biāo)對(duì)象有很多直接和間接觀察者奏甫,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。
(2)觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對(duì)象是怎么發(fā)生變化的凌受,而僅僅只是知道觀察目標(biāo)發(fā)生了變化阵子。

適用場(chǎng)景:
(1)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一個(gè)方面胜蛉,將這兩個(gè)方面封裝在獨(dú)立的對(duì)象中使它們可以各自獨(dú)立地改變和復(fù)用挠进。
(2)一個(gè)對(duì)象的改變將導(dǎo)致一個(gè)或多個(gè)其他對(duì)象也發(fā)生改變色乾,而并不知道具體有多少對(duì)象將發(fā)生改變,也不知道這些對(duì)象是誰(shuí)领突。
(3)需要在系統(tǒng)中創(chuàng)建一個(gè)觸發(fā)鏈暖璧,A對(duì)象的行為將影響B(tài)對(duì)象,B對(duì)象的行為將影響C對(duì)象……君旦,可以使用觀察者模式創(chuàng)建一種鏈?zhǔn)接|發(fā)機(jī)制澎办。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市金砍,隨后出現(xiàn)的幾起案子局蚀,更是在濱河造成了極大的恐慌,老刑警劉巖恕稠,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琅绅,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡谱俭,警方通過(guò)查閱死者的電腦和手機(jī)奉件,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門宵蛀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)昆著,“玉大人,你說(shuō)我怎么就攤上這事术陶〈斩” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵梧宫,是天一觀的道長(zhǎng)接谨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)塘匣,這世上最難降的妖魔是什么脓豪? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮忌卤,結(jié)果婚禮上扫夜,老公的妹妹穿的比我還像新娘。我一直安慰自己驰徊,他們只是感情好笤闯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棍厂,像睡著了一般颗味。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牺弹,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天浦马,我揣著相機(jī)與錄音时呀,去河邊找鬼。 笑死晶默,一個(gè)胖子當(dāng)著我的面吹牛退唠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荤胁,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼瞧预,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了仅政?” 一聲冷哼從身側(cè)響起垢油,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎圆丹,沒想到半個(gè)月后滩愁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辫封,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年硝枉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倦微。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡妻味,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出欣福,到底是詐尸還是另有隱情责球,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布拓劝,位于F島的核電站雏逾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏郑临。R本人自食惡果不足惜栖博,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厢洞。 院中可真熱鬧仇让,春花似錦、人聲如沸犀变。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)获枝。三九已至蠢正,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間省店,已是汗流浹背嚣崭。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工笨触, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雹舀。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓芦劣,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親说榆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子虚吟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 下面總結(jié)設(shè)計(jì)模式中的行為型模式: 1.責(zé)任鏈模式 顧名思義,責(zé)任鏈模式(Chain of Responsibili...
    Steven1997閱讀 3,471評(píng)論 0 1
  • 行為型模式用于描述程序在運(yùn)行時(shí)復(fù)雜的流程控制签财,即描述多個(gè)類或?qū)ο笾g怎樣相互協(xié)作共同完成單個(gè)對(duì)象都無(wú)法單獨(dú)完成的任...
    jiangmo閱讀 764評(píng)論 0 1
  • javascript設(shè)計(jì)模式與開發(fā)實(shí)踐 設(shè)計(jì)模式 每個(gè)設(shè)計(jì)模式我們需要從三點(diǎn)問(wèn)題入手: 定義 作用 用法與實(shí)現(xiàn) 單...
    穿牛仔褲的蚊子閱讀 4,065評(píng)論 0 13
  • 用來(lái)對(duì)類或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)進(jìn)行描述 1.模板方法2.命令模式3.策略模式4.觀察者模式 1.模板方法 1...
    木魚_cc閱讀 659評(píng)論 0 0
  • 這里是對(duì)《設(shè)計(jì)模式Java版》[https://gof.quanke.name]的提煉匯總唱蒸,在真正深入理解之前邦鲫,方...
    LeonXtp閱讀 1,009評(píng)論 0 0