前几天看到有个朋友写的一篇blog
题目如下:猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。
要求:(1)要有联动性,老鼠和人的行为是被动的。
(2)考虑可扩展性,猫叫声可能会引起其他的联动效应。
我不是一个善于做题目的人,但是这个题目想到了观察者设计模式,猫是目标,老鼠和主人是观察者,在猫叫的时候,通知老鼠和主人行动。
另外联动效应部分采用策略设计模式。这样如果有其他的联动效应可以加进来而不影响原有的效应。满足开放封闭原则。
我实现了一个C++版本的,代码如下:
目标类:
#include <list>
using namespace std;
#include "Observer.h"
class Observer;
class Subject
{
public:
virtual ~Subject(void);
virtual void Attach(Observer*);
virtual void Detach(Observer*);
virtual void Notify();
protected:
Subject(void);
private:
list<Observer*> _observers;
};
//实现代码:
Subject::Subject(void)
{
}
Subject::~Subject(void)
{
}
void Subject::Attach(Observer* o)
{
_observers.push_back(o);
}
void Subject::Detach(Observer* o)
{
_observers.remove(o);
}
void Subject::Notify()
{
list<Observer*>::iterator iter;
for(iter=_observers.begin();iter!=_observers.end();iter++)
(*iter)->Update(this);
}
观察者基类头文件:
class Subject;
class Reaction;
class Observer
{
public:
virtual ~Observer(void) {}
virtual void Update(Subject* theChangedSubject)=0;
void changeAction(Reaction *p);
protected:
Observer(Reaction* pAct):pAction(pAct) {}
Reaction *pAction;
};
实现文件:
#include "Observer.h"
void Observer::changeAction(Reaction *p)
{
pAction=p;
}
定义Cat类:
#include "Subject.h"
class Cat:public Subject
{
public:
Cat(void);
~Cat(void);
void Cry();
};
//实现:
#include "Cat.h"
Cat::Cat(void)
{
}
Cat::~Cat(void)
{
}
void Cat::Cry()
{
cout<<"Crying..."<<endl;
Notify();
}
老鼠类定义:
头文件:
#include "observer.h"
class Reaction;
class Cat;
class Mouse :public Observer
{
public:
Mouse(Cat* pc,Reaction* pAct);
~Mouse(void);
void Update(Subject* theChangedSubject);
private:
Cat* pc;
};
实现文件:
#include "Mouse.h"
#include "Reaction.h"
#include "Cat.h"
Mouse::Mouse(Cat* pc,Reaction* pAct):pc(pc),Observer(pAct)
{
pc->Attach(this);
}
Mouse::~Mouse(void)
{
pc->Detach(this);
}
void Mouse::Update(Subject* theChangedSubject)
{
if(theChangedSubject==pc)
{
pAction->Action();
}
}
主人类定义:
头文件:
#include "Observer.h"
class Cat;
class Reaction;
class Man :
public Observer
{
public:
Man(Cat* pc,Reaction* pAct);
~Man(void);
void Update(Subject* theChangedSubject);
private:
Cat* pc;
};
联动反应的类:
class Reaction
{
public:
Reaction() {}
~Reaction(void){}
virtual void Action()=0;
};
class Running:public Reaction
{
public:
void Action()
{
cout<<"Running..."<<endl;
}
};
class Wakeup:public Reaction
{
public:
void Action()
{
cout<<"Wakeup..."<<endl;
}
};
实现文件:
#include "Cat.h"
#include "Man.h"
#include "Reaction.h"
Man::Man(Cat* pc,Reaction* pAct):pc(pc),Observer(pAct)
{
pc->Attach(this);
}
Man::~Man(void)
{
pc->Detach(this);
}
void Man::Update(Subject* theChangedSubject)
{
if(theChangedSubject==pc)
{
pAction->Action();
}
}
测试代码:
#include "Cat.h"
#include "Mouse.h"
#include "Man.h"
#include "Reaction.h"
int _tmain(int argc, _TCHAR* argv[])
{
Cat* pc=new Cat();
Reaction* pMouseAction=new Running();
Mouse* pm1=new Mouse(pc,pMouseAction);
Mouse* pm2=new Mouse(pc,pMouseAction);
Reaction *pManAction=new Wakeup();
Man* pMan=new Man(pc,pManAction);
pc->Cry();
delete pMan;
delete pm1;
delete pm2;
delete pc;
delete pMouseAction;
delete pManAction;
return 0;
}
运行结果:
通过以上代码,达到了在猫叫的时候,两个老鼠逃跑和主人惊醒的目的。
总结:
观察者设计模式的使用性:
(1)当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中,以使他们可以各自独立的改变和复用。
(2)当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
(3)当一个对象必须通知其他对象,而它又不能假定其他对象是谁,换言之,你不希望这些对象是紧密耦合的。