猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒

前几天看到有个朋友写的一篇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)当一个对象必须通知其他对象,而它又不能假定其他对象是谁,换言之,你不希望这些对象是紧密耦合的。


 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值