一、什么是观察者模式
Observer模式也叫观察者模式,是由GoF提出的23种软件设计模式的一种。Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在刚才的例子中,业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。
“观察”不是“直接调用”
实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。
实现观察者模式的形式
实现观察者模式有很多形式,比较直观的一种是使用一种“注册——通知——撤销注册”的形式。
- /************************************************************************/
- /* 观察者模式 */
- /************************************************************************/
- #include <LIST>
- #include <STRING>
- #include <iostream>
- using namespace std;
- /*
- 编程要点:观察者接口要有一个更新自身状态的行为
- 被观察者(主题):要有一个存放与之相联系的观察者的链表,并有一个通知的行为,当被观察者的状态发生改变时,
- 它会通知所有与之相关联地具体观察者,即调用与之关联的观察者的Update方法
- */
- class Subject;
- //观察者接口(抽象)
- class Observer{
- public:
- virtual ~Observer(){};
- virtual void Update(Subject *concreteSubject){};//根据被观察者更新自身状态
- };
- //被观察者(主题)
- class Subject
- {
- private:
- list<Observer*> *obvs;
- public:
- //构造函数
- Subject()
- {
- obvs = new list<Observer*>;
- }
- void Attach(Observer *observer)
- {
- obvs->push_front(observer);//向链表中加入一个待通知的观察者
- }
- void Detach(Observer *observer)
- {
- obvs->push_back(observer);//删除一个观察者
- }
- //通知每个观察者
- void Notify()
- {
- list<Observer*>::iterator it;
- it = obvs->begin();
- for(;it!=obvs->end();it++){
- (*it)->Update(this);//每个观察者被通知后更新自己的状态
- }
- }
- public:
- virtual char* getState(){return NULL;}
- virtual void setState(){}
- };
- /*具体的主题*/
- class ConcreteSubject : public Subject
- {
- private:
- char *state;//被观察者的状态
- public:
- /*被观察者自身状态的设置与获取*/
- char* getState()
- {
- return state;
- }
- void setState(char *state)
- {
- this->state = state;
- }
- };
- //具体的观察者
- class ConcreteObserverA : public Observer
- {
- private:
- char *name;//名称
- char *state;//状态
- public:
- ConcreteObserverA(char *name)
- {
- this->name = name;
- }
- void Update(Subject *concreteSubject)
- {
- state = concreteSubject->getState();//更新自身状态
- cout<<"观察者:"<<name<<"的新状态是:"<<state<<endl;
- }
- };
- void main()
- {
- //构造一个主题
- ConcreteSubject *concreteSubject = new ConcreteSubject();
- //让主题和观察者相联系
- concreteSubject->Attach(new ConcreteObserverA("X"));
- concreteSubject->Attach(new ConcreteObserverA("Y"));
- //主题状态改变,并通知观察者
- concreteSubject->setState("老师走了,大家可以玩了,哈哈");
- concreteSubject->Notify();
- printf("过了一段时间后........................\n");
- //主题状态改变,再次通知观察者
- concreteSubject->setState("老师来了,大家别说了");
- concreteSubject->Notify();
- }
/************************************************************************/
/* 观察者模式 */
/************************************************************************/
#include <LIST>
#include <STRING>
#include <iostream>
using namespace std;
/*
编程要点:观察者接口要有一个更新自身状态的行为
被观察者(主题):要有一个存放与之相联系的观察者的链表,并有一个通知的行为,当被观察者的状态发生改变时,
它会通知所有与之相关联地具体观察者,即调用与之关联的观察者的Update方法
*/
class Subject;
//观察者接口(抽象)
class Observer{
public:
virtual ~Observer(){};
virtual void Update(Subject *concreteSubject){};//根据被观察者更新自身状态
};
//被观察者(主题)
class Subject
{
private:
list<Observer*> *obvs;
public:
//构造函数
Subject()
{
obvs = new list<Observer*>;
}
void Attach(Observer *observer)
{
obvs->push_front(observer);//向链表中加入一个待通知的观察者
}
void Detach(Observer *observer)
{
obvs->push_back(observer);//删除一个观察者
}
//通知每个观察者
void Notify()
{
list<Observer*>::iterator it;
it = obvs->begin();
for(;it!=obvs->end();it++){
(*it)->Update(this);//每个观察者被通知后更新自己的状态
}
}
public:
virtual char* getState(){return NULL;}
virtual void setState(){}
};
/*具体的主题*/
class ConcreteSubject : public Subject
{
private:
char *state;//被观察者的状态
public:
/*被观察者自身状态的设置与获取*/
char* getState()
{
return state;
}
void setState(char *state)
{
this->state = state;
}
};
//具体的观察者
class ConcreteObserverA : public Observer
{
private:
char *name;//名称
char *state;//状态
public:
ConcreteObserverA(char *name)
{
this->name = name;
}
void Update(Subject *concreteSubject)
{
state = concreteSubject->getState();//更新自身状态
cout<<"观察者:"<<name<<"的新状态是:"<<state<<endl;
}
};
void main()
{
//构造一个主题
ConcreteSubject *concreteSubject = new ConcreteSubject();
//让主题和观察者相联系
concreteSubject->Attach(new ConcreteObserverA("X"));
concreteSubject->Attach(new ConcreteObserverA("Y"));
//主题状态改变,并通知观察者
concreteSubject->setState("老师走了,大家可以玩了,哈哈");
concreteSubject->Notify();
printf("过了一段时间后........................\n");
//主题状态改变,再次通知观察者
concreteSubject->setState("老师来了,大家别说了");
concreteSubject->Notify();
}