設(shè)計模式5 行為模式
創(chuàng)新互聯(lián)主要從事成都做網(wǎng)站、網(wǎng)站設(shè)計、外貿(mào)營銷網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務廣州,10多年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18982081108
行為模式,目錄: 模式方法模式 命令模式 策略模式觀察者模式
模板方法模式:沖咖啡,沖茶水
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; //抽象的制作飲料方法 class MakeDrink { public: //1 把水煮開 void boil() { cout << "把水煮開" << endl; } //2 沖某物 virtual void brew() = 0; //3 從大杯倒入小杯 void putInCup() { cout << "把沖泡好的飲料 從大杯倒入小杯" << endl; } //4 加一些酌料 virtual void addThings() = 0; //鉤子函數(shù), hook virtual bool CustomWantAddThings() { return true; } //業(yè)務的邏輯的統(tǒng)一模板 void make() { boil(); brew(); //子類 putInCup(); if (CustomWantAddThings() == true) { addThings(); //子類的多態(tài) } } }; //制作咖啡 class MakeCoffee :public MakeDrink { public: MakeCoffee(bool isAdd) { this->isAdd = isAdd; } //2 沖某物 virtual void brew() { cout << "沖泡咖啡豆" << endl; } //4 加一些酌料 virtual void addThings() { cout << "添加糖和牛奶" << endl; } virtual bool CustomWantAddThings() { return isAdd; } private: bool isAdd; }; //沖泡茶葉 class MakeTea :public MakeDrink { public: MakeTea(bool isAdd) { this->isAdd = isAdd; } //2 沖某物 virtual void brew() { cout << "沖泡 茶葉" << endl; } //4 加一些酌料 virtual void addThings() { cout << "添加 檸檬 或者 菊花" << endl; } virtual bool CustomWantAddThings() { return isAdd; } private: bool isAdd; }; int main(void) { MakeDrink *makeCoffee = new MakeCoffee(true); makeCoffee->make(); cout << " ------ " << endl; MakeDrink *makeTea = new MakeTea(false); makeTea->make(); return 0; } chunli@linux:~$ g++ main.cpp && ./a.out 把水煮開 沖泡咖啡豆 把沖泡好的飲料 從大杯倒入小杯 添加糖和牛奶 ------ 把水煮開 沖泡 茶葉 把沖泡好的飲料 從大杯倒入小杯 chunli@linux:~$
模板方法模式中的角色和職責
AbstractClass(抽象類):在抽象類中定義了一系列基本操作
(PrimitiveOperations),這些基本操作可以是具體的,也可以是抽象的,每一
個基本操作對應算法的一個步驟,在其子類中可以重定義或?qū)崿F(xiàn)這些步驟。同
時,在抽象類中實現(xiàn)了一個模板方法(Template Method),用于定義一個算法
的框架,模板方法不僅可以調(diào)用在抽象類中實現(xiàn)的基本方法,也可以調(diào)用在抽
象類的子類中實現(xiàn)的基本方法,還可以調(diào)用其他對象中的方法。
ConcreteClass(具體子類): 它是抽象類的子類,用于實現(xiàn)在父類中聲
明的抽象基本操作以完成子類特定算法的步驟,也可以覆蓋在父類中已經(jīng)實現(xiàn)
的具體基本操作。
模板方法的優(yōu)缺點
優(yōu)點:
(1) 在父類中形式化地定義一個算法,而由它的子類來實現(xiàn)細節(jié)的處理,在
子類實現(xiàn)詳細的處理算法時并不會改變算法中步驟的執(zhí)行次序。
(2) 模板方法模式是一種代碼復用技術(shù),它在類庫設(shè)計中尤為重要,它提取
了類庫中的公共行為,將公共行為放在父類中,而通過其子類來實現(xiàn)不同的行
為,它鼓勵我們恰當使用繼承來實現(xiàn)代碼復用。
(3) 可實現(xiàn)一種反向控制結(jié)構(gòu),通過子類覆蓋父類的鉤子方法來決定某一特
定步驟是否需要執(zhí)行。
(4) 在模板方法模式中可以通過子類來覆蓋父類的基本方法,不同的子類可
以提供基本方法的不同實現(xiàn),更換和增加新的子類很方便,符合單一職責原則
和開閉原則。
缺點:
需要為每一個基本方法的不同實現(xiàn)提供一個子類,如果父類中可變的基本
方法太多,將會導致類的個數(shù)增加,系統(tǒng)更加龐大,設(shè)計也更加抽象。
適用場景
(1)具有統(tǒng)一的操作步驟或操作過程;
(2) 具有不同的操作細節(jié);
(3) 存在多個具有同樣操作步驟的應用場景,但某些具體的操作細節(jié)卻各
不相同;
在抽象類中統(tǒng)一操作步驟,并規(guī)定好接口;讓子類實現(xiàn)接口。這樣
可以把各個具體的子類和操作步驟解耦合。
命令模式:病人看病直接找醫(yī)生,耦合度太高.
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; class Doctor { public: void treatEyes() { cout <<"treat eyes " << endl; } void treatNose() { cout <<"treat nose" << endl; } }; int main(void) { Doctor *doctor = new Doctor; doctor->treatEyes(); doctor->treatNose(); return 0; } chunli@linux:~$ g++ main.cpp && ./a.out treat eyes treat nose chunli@linux:~$
拿著病單來看醫(yī)生,醫(yī)生只跟病單打交道
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; class Doctor { public: void treatEyes() { cout <<"treat eyes " << endl; } void treatNose() { cout <<"treat nose" << endl; } }; class CommandEyes { public: CommandEyes(Doctor* doctor) { this->doctor = doctor; } ~CommandEyes() { if(this->doctor != NULL) { delete this->doctor; this->doctor = NULL; } } void treat() { this->doctor->treatEyes(); } private: Doctor *doctor; }; class CommandNose { public: CommandNose(Doctor* doctor) { this->doctor = doctor; } ~CommandNose() { if(this->doctor != NULL) { delete this->doctor; this->doctor = NULL; } } void treat() { this->doctor->treatNose(); } private: Doctor *doctor; }; int main(void) { //拿著病單來看醫(yī)生 CommandEyes *commandEyes =new CommandEyes(new Doctor); commandEyes->treat(); CommandNose *commandNose =new CommandNose(new Doctor); commandNose->treat(); return 0; } chunli@linux:~$ g++ main.cpp && ./a.out treat eyes treat nose chunli@linux:~$
將病單抽象出來
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; class Doctor { public: void treatEyes() { cout <<"treat eyes " << endl; } void treatNose() { cout <<"treat nose" << endl; } }; class Command { public: Command(Doctor *doctor) { this->doctor = doctor; } ~Command() { if(this->doctor != NULL) { delete this->doctor; this->doctor = NULL; } } virtual void treat() = 0; protected: Doctor *doctor; }; class CommandEyes:public Command { public: CommandEyes(Doctor* doctor):Command(doctor) {} void treat() { this->doctor->treatEyes(); } }; class CommandNose:public Command { public: CommandNose(Doctor* doctor):Command(doctor) {} void treat() { this->doctor->treatNose(); } }; int main(void) { Command *comd1 =new CommandEyes(new Doctor); comd1->treat(); Command *comd2 =new CommandNose(new Doctor); comd2->treat(); return 0; } chunli@linux:~$ g++ main.cpp && ./a.out treat eyes treat nose chunli@linux:~$
讓護士接病單,通知病人來看病:
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; class Doctor { public: void treatEyes() { cout <<"treat eyes " << endl; } void treatNose() { cout <<"treat nose" << endl; } }; class Command { public: Command(Doctor *doctor) { this->doctor = doctor; } ~Command() { if(this->doctor != NULL) { delete this->doctor; this->doctor = NULL; } } virtual void treat() = 0; protected: Doctor *doctor; }; class CommandEyes:public Command { public: CommandEyes(Doctor* doctor):Command(doctor) {} void treat() { this->doctor->treatEyes(); } }; class CommandNose:public Command { public: CommandNose(Doctor* doctor):Command(doctor) {} void treat() { this->doctor->treatNose(); } }; class Nurse { public: Nurse(Command *cmd) { this->cmd = cmd; } ~Nurse() { if(this->cmd != NULL) { delete this->cmd; this->cmd = NULL; } } void notify() { this->cmd->treat(); } private: Command *cmd; }; int main(void) { Nurse *nurse = new Nurse(new CommandEyes(new Doctor)); nurse->notify(); Nurse *nurse2 = new Nurse(new CommandNose(new Doctor)); nurse2->notify(); return 0; } chunli@linux:~$ g++ main.cpp && ./a.out treat eyes treat nose chunli@linux:~$
把病單全部給護士長,讓護士長下發(fā)
chunli@linux:~$ cat main.cpp #include <iostream> #include <list> using namespace std; class Doctor { public: void treatEyes() { cout <<"treat eyes " << endl; } void treatNose() { cout <<"treat nose" << endl; } }; class Command { public: Command(Doctor *doctor) { this->doctor = doctor; } virtual ~Command() { if(this->doctor != NULL) { delete this->doctor; this->doctor = NULL; } } virtual void treat() = 0; protected: Doctor *doctor; }; class CommandEyes:public Command { public: CommandEyes(Doctor* doctor):Command(doctor) {} void treat() { this->doctor->treatEyes(); } }; class CommandNose:public Command { public: CommandNose(Doctor* doctor):Command(doctor) {} void treat() { this->doctor->treatNose(); } }; class Nurse { public: Nurse(Command *cmd) { this->cmd = cmd; } ~Nurse() { if(this->cmd != NULL) { delete this->cmd; this->cmd = NULL; } } void notify() { this->cmd->treat(); } private: Command *cmd; }; class NurseBoss { public: NurseBoss() { m_list.clear(); } ~NurseBoss() { m_list.clear(); } void setCmd(Command *cmd) { m_list.push_back(cmd); } void notify() { for(list<Command*>::iterator it = m_list.begin();it!=m_list.end();it++) { (*it)->treat(); } } private: list<Command*> m_list; }; int main(void) { NurseBoss *woman = new NurseBoss; Command *cmd1 = new CommandEyes(new Doctor); Command *cmd2 = new CommandNose(new Doctor); woman->setCmd(cmd1); woman->setCmd(cmd2); woman->notify(); return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out treat eyes treat nose chunli@linux:~$
命令模式,路邊吃烤串案例
chunli@linux:~$ cat main.cpp #include <iostream> #include <list> using namespace std; class Cooker { public: void makeChuaner() { cout << "正在烤串 " << endl; } void makeChicken() { cout << "正在烤雞翅 " << endl; } }; class Command { public: Command(Cooker * cooker) { this->cooker = cooker; } virtual ~Command() { if(this->cooker != NULL) { delete this->cooker; this->cooker = NULL; } } virtual void execute() = 0; protected: Cooker * cooker; }; class CommandChuaner:public Command { public: CommandChuaner(Cooker * cooker):Command(cooker) {} virtual void execute() { this->cooker->makeChuaner(); } }; class CommandChicken:public Command { public: CommandChicken(Cooker * cooker):Command(cooker) {} virtual void execute() { this->cooker->makeChicken(); } }; class Waitress { public: Waitress() { this->m_list.clear(); } ~Waitress() { this->m_list.clear(); } void setCmd(Command *cmd) { this->m_list.push_back(cmd); } void notify() { list<Command*>::iterator it = m_list.begin(); for(;it != m_list.end();it++) { (*it)->execute();//在此發(fā)生了多態(tài) } } private: list<Command*> m_list; }; int main(void) { Waitress *mm = new Waitress; //喊一個服務器 Command *chuaner = new CommandChuaner(new Cooker);//點菜單 Command *chicken = new CommandChicken(new Cooker);//點菜單 mm->setCmd(chuaner);//服務員登記 mm->setCmd(chicken); mm->notify(); //服務員端菜 return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 正在烤串 正在烤雞翅 chunli@linux:~$
命令模式中的角色和職責 [圖]
Command(抽象命令類): 抽象命令類一般是一個抽象類或接口,在
其中聲明了用于執(zhí)行請求的execute()等方法,通過這些方法可以調(diào)用請求接收
者的相關(guān)操作。
ConcreteCommand(具體命令類):具體命令類是抽象命令類的子
類,實現(xiàn)了在抽象命令類中聲明的方法,它對應具體的接收者對象,將接收者
對象的動作綁定其中。在實現(xiàn)execute()方法時,將調(diào)用接收者對象的相關(guān)操作
(Action)。
Invoker(調(diào)用者): 調(diào)用者即請求發(fā)送者,它通過命令對象來執(zhí)行請
求。一個調(diào)用者并不需要在設(shè)計時確定其接收者,因此它只與抽象命令類之間
存在關(guān)聯(lián)關(guān)系。在程序運行時可以將一個具體命令對象注入其中,再調(diào)用具體
命令對象的execute()方法,從而實現(xiàn)間接調(diào)用請求接收者的相關(guān)操作。
Receiver(接收者): 接收者執(zhí)行與請求相關(guān)的操作,它具體實現(xiàn)對請
求的業(yè)務處理。
5.2.3 命令模式的優(yōu)缺點
優(yōu)點:
(1) 降低系統(tǒng)的耦合度。由于請求者與接收者之間不存在直接引用,因此請
求者與接收者之間實現(xiàn)完全解耦,相同的請求者可以對應不同的接收者,同樣,
相同的接收者也可以供不同的請求者使用,兩者之間具有良好的獨立性。
(2) 新的命令可以很容易地加入到系統(tǒng)中。由于增加新的具體命令類不會影
響到其他類,因此增加新的具體命令類很容易,無須修改原有系統(tǒng)源代碼,甚
至客戶類代碼,滿足“開閉原則”的要求。
(3) 可以比較容易地設(shè)計一個命令隊列或宏命令(組合命令)。
缺點:
使用命令模式可能會導致某些系統(tǒng)有過多的具體命令類。因為針對每一個
對請求接收者的調(diào)用操作都需要設(shè)計一個具體命令類,因此在某些系統(tǒng)中可能
需要提供大量的具體命令類,這將影響命令模式的使用。
5.2.4 適用場景
(1) 系統(tǒng)需要將請求調(diào)用者和請求接收者解耦,使得調(diào)用者和接收者不直
接交互。請求調(diào)用者無須知道接收者的存在,也無須知道接收者是誰,接收者
也無須關(guān)心何時被調(diào)用。
(2) 系統(tǒng)需要在不同的時間指定請求、將請求排隊和執(zhí)行請求。一個命令
對象和請求的初始調(diào)用者可以有不同的生命期,換言之,最初的請求發(fā)出者可
能已經(jīng)不在了,而命令對象本身仍然是活動的,可以通過該命令對象去調(diào)用請
求接收者,而無須關(guān)心請求調(diào)用者的存在性,可以通過請求日志文件等機制來
具體實現(xiàn)。
(3) 系統(tǒng)需要將一組操作組合在一起形成宏命令。
===========================================
策略模式,英雄更換裝備戰(zhàn)斗場景
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; class AbstractStrategy//抽象的策略 { public: virtual void useWeapon() = 0; }; class KnifeStrategy:public AbstractStrategy { public: virtual void useWeapon() { cout << "使用 ××× " << endl; } }; class AKStrategy:public AbstractStrategy { public: virtual void useWeapon() { cout << "使用 AK47 " << endl; } }; class Hero { public: Hero() { strategy = NULL; } void setStrategy(AbstractStrategy * strategy) { this->strategy = strategy; } void fight() { cout << "英雄開始戰(zhàn)斗" << endl; this->strategy->useWeapon(); } private: AbstractStrategy *strategy; }; int main(void) { AbstractStrategy * knife = new KnifeStrategy; AbstractStrategy * ak47 = new AKStrategy; Hero *hero = new Hero ; cout << "---------------兵快來了,換AK47------------" << endl; hero->setStrategy(ak47); hero->fight(); cout << "---------------近距離搏斗,換AK47------------" << endl; hero->setStrategy(knife); hero->fight(); return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out ---------------兵快來了,換AK47------------ 英雄開始戰(zhàn)斗 使用 AK47 ---------------近距離搏斗,換AK47------------ 英雄開始戰(zhàn)斗 使用 ××× chunli@linux:~$
策略模式,不同時間不同的銷售模式
chunli@linux:~$ cat main.cpp #include <iostream> using namespace std; class AbstractStrategy { public: virtual double getPrice(double price) = 0; }; class StrategyA:public AbstractStrategy//8折策略 { public: virtual double getPrice(double price) { return price*0.8; } }; class StrategyB:public AbstractStrategy //滿200減100策略 { public: virtual double getPrice(double price) { if(price > 200) { price -= 100; } return price; } }; class Item { public: Item(string name,double price) { this->name = name; this->price = price; } double SellPrice() { return this->strategy->getPrice(this->price); } void setStrategy(AbstractStrategy * strategy) { this->strategy = strategy; } private: string name; double price; AbstractStrategy * strategy; }; int main(void) { Item it("nike鞋",201); AbstractStrategy *sa = new StrategyA; AbstractStrategy *sb = new StrategyB; cout << "上午,全場8折" << endl; it.setStrategy(sa); cout << "nike鞋應該賣" <<it.SellPrice() << endl; cout << "下午,全場滿200減100" << endl; it.setStrategy(sb); cout << "nike鞋應該賣" <<it.SellPrice() << endl; return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 上午,全場8折 nike鞋應該賣160.8 下午,全場滿200減100 nike鞋應該賣101 chunli@linux:~$
策略模式中的角色和職責[圖]
Context(環(huán)境類): 環(huán)境類是使用算法的角色,它在解決某個問題(即
實現(xiàn)某個方法)時可以采用多種策略。在環(huán)境類中維持一個對抽象策略類的引
用實例,用于定義所采用的策略。
Strategy(抽象策略類): 它為所支持的算法聲明了抽象方法,是所有
策略類的父類,它可以是抽象類或具體類,也可以是接口。環(huán)境類通過抽象策
略類中聲明的方法在運行時調(diào)用具體策略類中實現(xiàn)的算法。
ConcreteStrategy(具體策略類):它實現(xiàn)了在抽象策略類中聲明的算
法,在運行時,具體策略類將覆蓋在環(huán)境類中定義的抽象策略類對象,使用一
種具體的算法實現(xiàn)某個業(yè)務處理。
5.3.3 策略模式的優(yōu)缺點
優(yōu)點:
(1) 策略模式提供了對“開閉原則”的完美支持, 用戶可以在不修改原有系
統(tǒng)的基礎(chǔ)上選擇算法或行為,也可以靈活地增加新的算法或行為。
(2) 使用策略模式可以避免多重條件選擇語句。多重條件選擇語句不易維護,
它把采取哪一種算法或行為的邏輯與算法或行為本身的實現(xiàn)邏輯混合在一起,
將它們?nèi)坑簿幋a(Hard Coding)在一個龐大的多重條件選擇語句中,比直接繼
承環(huán)境類的辦法還要原始和落后。
(3) 策略模式提供了一種算法的復用機制。由于將算法單獨提取出來封裝在
策略類中,因此不同的環(huán)境類可以方便地復用這些策略類。
缺點:
(1) 客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。這就意
味著客戶端必須理解這些算法的區(qū)別,以便適時選擇恰當?shù)乃惴?。換言之,策
略模式只適用于客戶端知道所有的算法或行為的情況。
(2) 策略模式將造成系統(tǒng)產(chǎn)生很多具體策略類,任何細小的變化都將導致系
統(tǒng)要增加一個新的具體策略類。
5.3.4 適用場景
準備一組算法,并將每一個算法封裝起來,使得它們可以互換。
=========================================
觀察者模式,班長給學生放風,學生抄作業(yè)
chunli@linux:~$ cat main.cpp #include <iostream> #include <list> using namespace std; //------------------------------------------ //抽象層的觀察者 class Listener//學生 { public: virtual void DoSomething() = 0;//該干的 virtual void DoOtherthing() = 0;//不該干的 }; //抽象的被觀察者 class Notify//班長 { public: virtual void addlistener(Listener *listener) = 0;//添加學生 virtual void dellistener(Listener *listener) = 0;//刪除學生 virtual void notify() = 0; //通知學生 }; //-------------------------------------------- class Student:public Listener//學生 { public: Student(string name,string badthing) { this->name = name; this->badthing = badthing; } virtual void DoSomething() { cout << "學生" <<name << "停止"<< badthing << ",改為寫作業(yè) " << endl; } virtual void DoOtherthing() { cout << "學生" <<name << "目前正在"<< badthing << endl; } private: string name; string badthing; }; class Monitor:public Notify { public: virtual void addlistener(Listener *listener) { this->m_list.push_back(listener); } virtual void dellistener(Listener *listener) { this->m_list.remove(listener); } virtual void notify() { list<Listener*>::iterator it = m_list.begin(); for(;it!= m_list.end();it++) { (*it)->DoSomething(); } } private: list<Listener*> m_list; }; int main(void) { Listener *s1 = new Student("吳用","智取生辰綱"); Listener *s2 = new Student("楊志","買刀"); Listener *s3 = new Student("武松","醉打蔣門神"); Notify *master = new Monitor; master->addlistener(s1); master->addlistener(s2); master->addlistener(s3); cout << "----老師沒有來,大家可以抄作業(yè)" << endl; s1->DoOtherthing(); s2->DoOtherthing(); s3->DoOtherthing(); cout << "----老師來了,大家該干啥干啥" << endl; master->notify(); return 0; } chunli@linux:~$ chunli@linux:~$ g++ main.cpp -Wall && ./a.out ----老師沒有來,大家可以抄作業(yè) 學生吳用目前正在智取生辰綱 學生楊志目前正在買刀 學生武松目前正在醉打蔣門神 ----老師來了,大家該干啥干啥 學生吳用停止智取生辰綱,改為寫作業(yè) 學生楊志停止買刀,改為寫作業(yè) 學生武松停止醉打蔣門神,改為寫作業(yè) chunli@linux:~$
觀察者模式,武林高手對決場景
chunli@linux:~$ cat main.cpp #include <iostream> #include <string> #include <list> using namespace std; //前置聲明notifier class Notifier; //抽象的觀察者 class Linstenner { public: //當朋友被揍了我改怎么辦 virtual void onFriendBeFight(Linstenner *one, Linstenner *another/*, Notifier *baixiao*/) = 0; //one是打別人的人, another 是被揍的 virtual void fighting(Linstenner *another, Notifier *notifier) = 0; virtual string getName() = 0; virtual string getParty() = 0; }; //抽象的通知者 class Notifier { public: //添加觀察者 virtual void addListenner(Linstenner *listenner) = 0; //刪除觀察者 virtual void delListenner(Linstenner *listenner) = 0; //通知觀察者 virtual void notify(Linstenner *one, Linstenner *another) = 0; }; // 武林中的人物 class Hero :public Linstenner { public: Hero(string name, string party) { this->name = name; this->party = party; } //當我發(fā)現(xiàn)一個消息之后我該怎么辦 virtual void onFriendBeFight(Linstenner *one, Linstenner *another/*, Notifier *baixiao*/) { if (another->getName() != this->name &&one->getName() != this->name) { //不是當事人 //如果不是當事人,需要判斷打人的pary 和 被打的party是不是我自己哥們 if (one->getParty() == this->party) { //自己人把 比人揍了 cout << name << "發(fā)現(xiàn)自己人把別人揍了, 笑了 , 拍手叫好" << endl; } else if (another->getParty() == this->party){ //自己人被揍了 cout << name << "發(fā)現(xiàn)自己人被別人走了, 出手援救" << endl; //this->fighting(one, baixiao); } } else { //當事人 //如果是當事人,什么都不敢 } } //揍人的方法 virtual void fighting(Linstenner *another, Notifier *notifier) { cout << name << "[" << this->party << "]" << " 把 " << another->getName() << "[" << another->getParty() << "]" << "給揍了" << endl; // 揍完之后,這個事件應該讓百曉生知曉 //應該調(diào)用百曉生 的notify方法 notifier->notify(this, another); } string getName() { return this->name; } string getParty() { return this->party; } private: string name; string party; }; class Baixiao :public Notifier { public: //添加觀察者 virtual void addListenner(Linstenner *listenner) { this->l_list.push_back(listenner); } //刪除觀察者 virtual void delListenner(Linstenner *listenner) { this->l_list.remove(listenner); } //通知觀察者 virtual void notify(Linstenner *one, Linstenner *another) { for (list<Linstenner *>::iterator it = l_list.begin(); it != l_list.end(); it++) { (*it)->onFriendBeFight(one, another/*, this*/); } } private: //擁有所有武林人士的名單 list<Linstenner*> l_list; }; int main(void) { Linstenner *hong7 = new Hero("洪七公", "丐幫"); Linstenner *huangrong = new Hero("黃蓉", "丐幫"); Linstenner *wuyazi = new Hero("無崖子", "逍遙派"); Linstenner *tonglao = new Hero("天山童姥", "逍遙派"); //創(chuàng)建一個百曉生 Notifier *baixiao = new Baixiao; //百曉生 手機全部的武林人士名單 baixiao->addListenner(hong7); baixiao->addListenner(huangrong); baixiao->addListenner(wuyazi); baixiao->addListenner(tonglao); //以上初始化完畢 hong7->fighting(wuyazi, baixiao); cout << "----" << endl; tonglao->fighting(hong7, baixiao); return 0; } chunli@linux:~$ g++ main.cpp && ./a.out 洪七公[丐幫] 把 無崖子[逍遙派]給揍了 黃蓉發(fā)現(xiàn)自己人把別人揍了, 笑了 , 拍手叫好 天山童姥發(fā)現(xiàn)自己人被別人走了, 出手援救 ---- 天山童姥[逍遙派] 把 洪七公[丐幫]給揍了 黃蓉發(fā)現(xiàn)自己人被別人走了, 出手援救 無崖子發(fā)現(xiàn)自己人把別人揍了, 笑了 , 拍手叫好 chunli@linux:~$
觀察者模式中的角色和職責 [圖]
Subject(被觀察者或目標,抽象主題):被觀察的對象。當需要被觀察的狀
態(tài)發(fā)生變化時,需要通知隊列中所有觀察者對象。Subject需要維持(添加,
刪除,通知)一個觀察者對象的隊列列表。
ConcreteSubject(具體被觀察者或目標,具體主題): 被觀察者的具體實
現(xiàn)。包含一些基本的屬性狀態(tài)及其他操作。
Observer(觀察者):接口或抽象類。當Subject的狀態(tài)發(fā)生變化時,
Observer對象將通過一個callback函數(shù)得到通知。
ConcreteObserver(具體觀察者):觀察者的具體實現(xiàn)。得到通知后將完成
一些具體的業(yè)務邏輯處理。
5.4.3 觀察者模式的優(yōu)缺點
優(yōu)點:
(1) 觀察者模式可以實現(xiàn)表示層和數(shù)據(jù)邏輯層的分離,定義了穩(wěn)定的消息更
新傳遞機制,并抽象了更新接口,使得可以有各種各樣不同的表示層充當具體
觀察者角色。
(2) 觀察者模式在觀察目標和觀察者之間建立一個抽象的耦合。觀察目標只
需要維持一個抽象觀察者的集合,無須了解其具體觀察者。由于觀察目標和觀
察者沒有緊密地耦合在一起,因此它們可以屬于不同的抽象化層次。
(3) 觀察者模式支持廣播通信,觀察目標會向所有已注冊的觀察者對象發(fā)送
通知,簡化了一對多系統(tǒng)設(shè)計的難度。
(4) 觀察者模式滿足“開閉原則”的要求,增加新的具體觀察者無須修改原
有系統(tǒng)代碼,在具體觀察者與觀察目標之間不存在關(guān)聯(lián)關(guān)系的情況下,增加新
的觀察目標也很方便。
缺點:
(1) 如果一個觀察目標對象有很多直接和間接觀察者,將所有的觀察者都通
知到會花費很多時間。
(2) 如果在觀察者和觀察目標之間存在循環(huán)依賴,觀察目標會觸發(fā)它們之間
進行循環(huán)調(diào)用,可能導致系統(tǒng)崩潰。
(3) 觀察者模式?jīng)]有相應的機制讓觀察者知道所觀察的目標對象是怎么發(fā)生
變化的,而僅僅只是知道觀察目標發(fā)生了變化。
5.4.4 適用場景
(1) 一個抽象模型有兩個方面,其中一個方面依賴于另一個方面,將這兩
個方面封裝在獨立的對象中使它們可以各自獨立地改變和復用。
(2) 一個對象的改變將導致一個或多個其他對象也發(fā)生改變,而并不知道
具體有多少對象將發(fā)生改變,也不知道這些對象是誰。
(3) 需要在系統(tǒng)中創(chuàng)建一個觸發(fā)鏈,A對象的行為將影響B(tài)對象,B對象的
行為將影響C對象……,可以使用觀察者模式創(chuàng)建一種鏈式觸發(fā)機制。
分享標題:設(shè)計模式5行為模式
文章來源:http://jinyejixie.com/article26/ipipjg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、電子商務、虛擬主機、網(wǎng)站制作、網(wǎng)頁設(shè)計公司、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)