设计模式之观察者模式(Observer)摘录
23種GOF設(shè)計(jì)模式一般分為三大類:創(chuàng)建型模式、結(jié)構(gòu)型模式、行為模式。
創(chuàng)建型模式抽象了實(shí)例化過(guò)程,它們幫助一個(gè)系統(tǒng)獨(dú)立于如何創(chuàng)建、組合和表示它的那些對(duì)象。一個(gè)類創(chuàng)建型模式使用繼承改變被實(shí)例化的類,而一個(gè)對(duì)象創(chuàng)建型模式將實(shí)例化委托給另一個(gè)對(duì)象。創(chuàng)建型模式有兩個(gè)不斷出現(xiàn)的主旋律。第一,它們都將關(guān)于該系統(tǒng)使用哪些具體的類的信息封裝起來(lái)。第二,它們隱藏了這些類的實(shí)例是如何被創(chuàng)建和放在一起的。整個(gè)系統(tǒng)關(guān)于這些對(duì)象所知道的是由抽象類所定義的接口。因此,創(chuàng)建型模式在什么被創(chuàng)建,誰(shuí)創(chuàng)建它,它是怎樣被創(chuàng)建的,以及何時(shí)創(chuàng)建這些方面給予了很大的靈活性。它們?cè)试S用結(jié)構(gòu)和功能差別很大的“產(chǎn)品”對(duì)象配置一個(gè)系統(tǒng)。配置可以是靜態(tài)的(即在編譯時(shí)指定),也可以是動(dòng)態(tài)的(在運(yùn)行時(shí))。
結(jié)構(gòu)型模式涉及到如何組合類和對(duì)象以獲得更大的結(jié)構(gòu)。結(jié)構(gòu)型類模式采用繼承機(jī)制來(lái)組合接口或?qū)崿F(xiàn)。結(jié)構(gòu)型對(duì)象模式不是對(duì)接口和實(shí)現(xiàn)進(jìn)行組合,而是描述了如何對(duì)一些對(duì)象進(jìn)行組合,從而實(shí)現(xiàn)新功能的一些方法。因?yàn)榭梢栽谶\(yùn)行時(shí)刻改變對(duì)象組合關(guān)系,所以對(duì)象組合方式具有更大的靈活性,而這種機(jī)制用靜態(tài)類組合是不可能實(shí)現(xiàn)的。
行為模式涉及到算法和對(duì)象間職責(zé)的分配。行為模式不僅描述對(duì)象或類的模式,還描述它們之間的通信模式。這些模式刻畫(huà)了在運(yùn)行時(shí)難以跟蹤的復(fù)雜的控制流。它們將用戶的注意力從控制流轉(zhuǎn)移到對(duì)象間的聯(lián)系方式上來(lái)。行為類模式使用繼承機(jī)制在類間分派行為。行為對(duì)象模式使用對(duì)象復(fù)合而不是繼承。一些行為對(duì)象模式描述了一組對(duì)等的對(duì)象怎樣相互協(xié)作以完成其中任一個(gè)對(duì)象都無(wú)法單獨(dú)完成的任務(wù)。
創(chuàng)建型模式包括:1、FactoryMethod(工廠方法模式);2、Abstract Factory(抽象工廠模式);3、Singleton(單例模式);4、Builder(建造者模式、生成器模式);5、Prototype(原型模式).
結(jié)構(gòu)型模式包括:6、Bridge(橋接模式);7、Adapter(適配器模式);8、Decorator(裝飾模式);9、Composite(組合模式);10、Flyweight(享元模式);11、Facade(外觀模式);12、Proxy(代理模式).
行為模式包括:13、TemplateMethod(模板方法模式);14、Strategy(策略模式);15、State(狀態(tài)模式);16、Observer(觀察者模式);17、Memento(備忘錄模式);18、Mediator(中介者模式);19、Command(命令模式);20、Visitor(訪問(wèn)者模式);21、Chain of Responsibility(責(zé)任鏈模式);22、Iterator(迭代器模式);23、Interpreter(解釋器模式).
Factory Method:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定將哪一個(gè)類實(shí)例化。Factory Method使一個(gè)類的實(shí)例化延遲到其子類。
Abstract Factory:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)需指定他們具體的類。
Singleton:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
Builder:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
Prototype:用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過(guò)拷貝這個(gè)原型來(lái)創(chuàng)建新的對(duì)象。
Bridge:將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。
Adapter:將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
Decorator:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就擴(kuò)展功能而言, Decorator模式比生成子類方式更為靈活。
Composite:將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。Composite使得客戶對(duì)單個(gè)對(duì)象和復(fù)合對(duì)象的使用具有一致性。
Flyweight:運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象。
Facade:為子系統(tǒng)中的一組接口提供一個(gè)一致的界面, Facade模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。
Proxy:為其他對(duì)象提供一個(gè)代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。
Template Method:定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
Strategy:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái), 并且使它們可相互替換。本模式使得算法的變化可獨(dú)立于使用它的客戶。
State:允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為。對(duì)象看起來(lái)似乎修改了它所屬的類。
Observer:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,以便當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)刷新。
Memento:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣以后就可將該對(duì)象恢復(fù)到保存的狀態(tài)。
Mediator:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互。中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。
Command:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使你可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可取消的操作。
Visitor:表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
Chain of Responsibility:為解除請(qǐng)求的發(fā)送者和接收者之間耦合,而使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它。
Iterator:提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中各個(gè)元素, 而又不需暴露該對(duì)象的內(nèi)部表示。
Interpreter:給定一個(gè)語(yǔ)言, 定義它的文法的一種表示,并定義一個(gè)解釋器, 該解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
???????? Observer:(1)、意圖:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。
???????? (2)、適用性:A、當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一方面。將這兩者封裝在獨(dú)立的對(duì)象中以使它們可以各自獨(dú)立地改變和復(fù)用。B、當(dāng)對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象,而不知道具體有多少對(duì)象有待改變。C、當(dāng)一個(gè)對(duì)象必須通知其它對(duì)象,而它又不能假定其它對(duì)象是誰(shuí)。換言之,你不希望這些對(duì)象是緊密耦合的。
???????? (3)、優(yōu)缺點(diǎn):A、目標(biāo)和觀察者間的抽象耦合:一個(gè)目標(biāo)所知道的僅僅是它有一系列觀察者,每個(gè)都符合抽象的Observer類的簡(jiǎn)單接口。目標(biāo)不知道任何一個(gè)觀察者屬于哪一個(gè)具體的類。這樣目標(biāo)和觀察者之間的耦合是抽象的和最小的。因?yàn)槟繕?biāo)和觀察者不是緊密耦合的,它們可以屬于一個(gè)系統(tǒng)中的不同抽象層次。一個(gè)處于較低層次的目標(biāo)對(duì)象可與一個(gè)處于較高層次的觀察者通信并通知它,這樣就保持了系統(tǒng)層次的完整。如果目標(biāo)和觀察者混在一塊,那么得到的對(duì)象要么橫貫兩個(gè)層次(違反了層次性),要么必須放在這兩層的某一層中(這可能會(huì)損害層次抽象)。B、支持廣播通信:不像通常的請(qǐng)求,目標(biāo)發(fā)送的通知不需指定它的接收者。通知被自動(dòng)廣播給所有已向該目標(biāo)對(duì)象登記的有關(guān)對(duì)象。目標(biāo)對(duì)象并不關(guān)心到底有多少對(duì)象對(duì)自己感興趣;它唯一的責(zé)任就是通知它的各觀察者。這給了你在任何時(shí)刻增加和刪除觀察者的自由。處理還是忽略一個(gè)通知取決于觀察者。C、意外的更新:因?yàn)橐粋€(gè)觀察者并不知道其它觀察者的存在,它可能對(duì)改變目標(biāo)的最終代價(jià)一無(wú)所知。在目標(biāo)上一個(gè)看似無(wú)害的操作可能會(huì)引起一系列對(duì)觀察者以及依賴于這些觀察者的那些對(duì)象的更新。此外,如果依賴準(zhǔn)則的定義或維護(hù)不當(dāng),常常會(huì)引起錯(cuò)誤的更新,這種錯(cuò)誤通常很難捕捉。簡(jiǎn)單的更新協(xié)議不提供具體細(xì)節(jié)說(shuō)明目標(biāo)中什么被改變了,這就使得上述問(wèn)題更加嚴(yán)重。如果沒(méi)有其他協(xié)議幫助觀察者發(fā)現(xiàn)什么發(fā)生了改變,它們可能會(huì)被迫盡力減少改變。
???????? (4)、相關(guān)模式:A、Mediator:通過(guò)封裝復(fù)雜的更新語(yǔ)義,ChangeManager(當(dāng)目標(biāo)和觀察者間的依賴關(guān)系特別復(fù)雜時(shí),可能需要一個(gè)維護(hù)這些關(guān)系的對(duì)象。我們稱這樣的對(duì)象為更改管理器。它的目的是盡量減少觀察者反映其目標(biāo)的狀態(tài)變化所需的工作量) 充當(dāng)目標(biāo)和觀察者之間的中介者。B、Singleton:ChangeManager可使用Singleton模式來(lái)保證它是唯一的并且是可全局訪問(wèn)的。
???????? (5)、觀察者模式:定義了一種一對(duì)多的關(guān)系,讓多個(gè)觀察對(duì)象同時(shí)監(jiān)聽(tīng)一個(gè)主題對(duì)象,主題對(duì)象狀態(tài)發(fā)生變化時(shí),會(huì)通知所有的觀察者,使它們能夠更新自己。
???????? (6)、Observer模式要解決的問(wèn)題為:建立一個(gè)一(Subject)對(duì)多(Observer)的依賴關(guān)系,并且做到當(dāng)“一”變化的時(shí)候,依賴這個(gè)”一”的多也能夠同步改變。最常見(jiàn)的一個(gè)例子就是:對(duì)同一組數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析的時(shí)候,我們希望能夠提供多種形式的表示(例如以表格進(jìn)行統(tǒng)計(jì)顯示、柱狀圖統(tǒng)計(jì)顯示、百分比統(tǒng)計(jì)顯示等)。這些表示都依賴于同一組數(shù)據(jù),我們當(dāng)然需要當(dāng)數(shù)據(jù)改變的時(shí)候,所有的統(tǒng)計(jì)的顯示都能夠同時(shí)改變。Observer模式就是解決了這一關(guān)問(wèn)題。
示例代碼1:
#include <string>
#include <iostream>
#include <vector>using namespace std;class Secretary;//看股票的同事類(觀察對(duì)象,觀察者)
class StockObserver
{
private:string name;Secretary* sub;
public:StockObserver(string strname, Secretary* strsub){name = strname;sub = strsub;}void Update();
};//秘書(shū)類(主題對(duì)象,通知者)
class Secretary
{
private:vector<StockObserver> observers;
public:string action;void Add(StockObserver ob){observers.push_back(ob);}void Notify(){vector<StockObserver>::iterator p = observers.begin();while (p != observers.end()){(*p).Update();p ++;}}
};void StockObserver::Update()
{cout<<name<<":"<<sub->action<<",不要玩股票了,要開(kāi)始工作了"<<endl;
}//客戶端
int main()
{Secretary* p = new Secretary();//創(chuàng)建通知者//觀察者StockObserver* s1 = new StockObserver("小李", p);StockObserver* s2 = new StockObserver("小趙", p);//加入通知隊(duì)列p->Add(*s1);p->Add(*s2);//事件p->action = "老板來(lái)了";//通知p->Notify();/*result小李:老板來(lái)了,不要玩股票了,要開(kāi)始工作了小趙:老板來(lái)了,不要玩股票了,要開(kāi)始工作了*/return 0;
}
示例代碼2:
#include <string>
#include <iostream>
#include <vector>using namespace std;class SecretaryBase;//抽象觀察者
class CObserverBase
{
protected:string name;SecretaryBase* sub;
public:CObserverBase(string strname, SecretaryBase* strsub){name = strname;sub = strsub;}virtual void Update() = 0;
};//具體的觀察者,看股票的
class StockObserver : public CObserverBase
{
public:StockObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub){}virtual void Update();
};//具體觀察者,看NBA的
class NBAObserver : public CObserverBase
{
public:NBAObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub){}virtual void Update();
};//抽象通知者
class SecretaryBase
{
public:string action;vector<CObserverBase*> observers;
public:virtual void Attach(CObserverBase* observer) = 0;virtual void Notify() = 0;
};//具體通知者
class Secretary : public SecretaryBase
{
public:void Attach(CObserverBase* ob){observers.push_back(ob);}void Notify(){vector<CObserverBase*>::iterator p = observers.begin();while (p != observers.end()){(*p)->Update();p ++;}}
};void StockObserver::Update()
{cout<<name<<":"<<sub->action<<"不要玩股票了,要開(kāi)始工作了"<<endl;
}void NBAObserver::Update()
{cout<<name<<":"<<sub->action<<"不要看NBA了,老板來(lái)了"<<endl;
}//客戶端
int main()
{SecretaryBase* p = new Secretary();//創(chuàng)建觀察者//被觀察的對(duì)象CObserverBase* s1 = new NBAObserver("小李", p);CObserverBase* s2 = new StockObserver("小趙", p);//加入觀察隊(duì)列p->Attach(s1);p->Attach(s2);//事件p->action = "老板來(lái)了";//通知p->Notify();/*result小李:老板來(lái)了不要看NBA了,老板來(lái)了小趙:老板來(lái)了不要玩股票了,要開(kāi)始工作了*/return 0;
}
示例代碼3:
Subject.h:
#ifndef _SUBJECT_H_
#define _SUBJECT_H_#include <list>
#include <string>using namespace std;typedef string State;class Observer;class Subject
{
public:virtual ~Subject();virtual void Attach(Observer* obv);virtual void Detach(Observer* obv);virtual void Notify();virtual void SetState(const State& st) = 0;virtual State GetState() = 0;
protected:Subject();
private:list<Observer*>* _obvs;
};class ConcreteSubject : public Subject
{
public:ConcreteSubject();~ConcreteSubject();State GetState();void SetState(const State& st);
protected:
private:State _st;
};#endif//~_SUBJECT_H_
Subject.cpp:
#include "Subject.h"
#include "Observer.h"#include <iostream>
#include <list>using namespace std;typedef string state;Subject::Subject()
{//在模板的使用之前一定要new,創(chuàng)建_obvs = new list<Observer*>;
}Subject::~Subject()
{}void Subject::Attach(Observer* obv)
{_obvs->push_front(obv);
}void Subject::Detach(Observer* obv)
{if (obv != NULL)_obvs->remove(obv);
}void Subject::Notify()
{list<Observer*>::iterator it;it = _obvs->begin();for (; it != _obvs->end(); it ++) //關(guān)于模板和iterator的用法(*it)->Update(this);
}ConcreteSubject::ConcreteSubject()
{_st = '\0';
}ConcreteSubject::~ConcreteSubject()
{}State ConcreteSubject::GetState()
{return _st;
}void ConcreteSubject::SetState(const State& st)
{_st = st;
}
Observer.h:
#ifndef _OBSERVER_H_
#define _OBSERVER_H_#include "Subject.h"
#include <string>using namespace std;typedef string State;class Observer
{
public:virtual ~Observer();virtual void Update(Subject* sub) = 0;virtual void PrintInfo() = 0;
protected:Observer();State _st;
private:
};class ConcreteObserverA : public Observer
{
public:virtual Subject* GetSubject();ConcreteObserverA(Subject* sub);virtual ~ConcreteObserverA();//傳入Subject作為參數(shù),這樣可以讓一個(gè)View屬于多個(gè)的Subjectvoid Update(Subject* sub);void PrintInfo();
protected:
private:Subject* _sub;
};class ConcreteObserverB : public Observer
{
public:virtual Subject* GetSubject();ConcreteObserverB(Subject* sub);virtual ~ConcreteObserverB();//傳入Subject作為參數(shù),這樣可以讓一個(gè)View屬于多個(gè)的Subjectvoid Update(Subject* sub);void PrintInfo();
protected:
private:Subject* _sub;
};#endif//~_OBSERVER_H_
Observer.cpp:
#include "Observer.h"
#include "Subject.h"#include <iostream>
#include <string>using namespace std;Observer::Observer()
{_st = '\0';
}Observer::~Observer()
{}ConcreteObserverA::ConcreteObserverA(Subject* sub)
{_sub = sub;_sub->Attach(this);
}ConcreteObserverA::~ConcreteObserverA()
{_sub->Detach(this);if (_sub != 0)delete _sub;
}Subject* ConcreteObserverA::GetSubject()
{return _sub;
}void ConcreteObserverA::PrintInfo()
{cout<<"ConcreteObserverA observer ..."<<_sub->GetState()<<endl;
}void ConcreteObserverA::Update(Subject* sub)
{_st = sub->GetState();PrintInfo();
}ConcreteObserverB::ConcreteObserverB(Subject* sub)
{_sub = sub;_sub->Attach(this);
}ConcreteObserverB::~ConcreteObserverB()
{_sub->Detach(this);if (_sub != 0)delete _sub;
}Subject* ConcreteObserverB::GetSubject()
{return _sub;
}void ConcreteObserverB::PrintInfo()
{cout<<"ConcreteObserverB observer ..."<<_sub->GetState()<<endl;
}void ConcreteObserverB::Update(Subject* sub)
{_st = sub->GetState();PrintInfo();
}
main.cpp:
#include "Subject.h"
#include "Observer.h"#include <iostream>using namespace std;int main()
{ConcreteSubject* sub = new ConcreteSubject();Observer* o1 = new ConcreteObserverA(sub);Observer* o2 = new ConcreteObserverB(sub);sub->SetState("old");sub->Notify();sub->SetState("new");//也可以由Observer調(diào)用sub->Notify();/*resultConcreteObserverB observer ...oldConcreteObserverA observer ...oldConcreteObserverB observer ...newConcreteObserverA observer ...new*/return 0;
}
觀察者模式結(jié)構(gòu)圖:
參考文獻(xiàn):
1、《大話設(shè)計(jì)模式C++》
2、《設(shè)計(jì)模式精解----GoF23種設(shè)計(jì)模式解析》
3、《設(shè)計(jì)模式----可復(fù)用面向?qū)ο筌浖幕A(chǔ)》
總結(jié)
以上是生活随笔為你收集整理的设计模式之观察者模式(Observer)摘录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 设计模式之状态模式(State)摘录
- 下一篇: 设计模式之备忘录模式(Memento)摘