设计模式之Observer模式(C++实现)

观察者模式(Observer)定义了对象间一对多的联系。当一个对象的状态发生变化时,所有与它有联系的观察者对象都会得到通知。观察者模式将被观察的目标和观察者解耦,一个目标可以有任意多的观察者,观察者也可以观察任意多的目标,构成复杂的联系,而每个观察者都不知道其他观察者的存在。

 

这里我就不列出那么多正式化的UML图了,那些是书本上的事,如果要详细学设计模式,推荐Gof的大话设计模式

 

我们在这里举两个例子来说明

第一:烧水瓶热水时候,当烧到97度的时候,显示屏会收到消息,然后再屏幕上显示当前温度,声控器会发出声音,提示报警!

第二:某软件公司突然来了一个性感的女秘书,程序员A和程序员B这两个钓丝按耐不住了,密切注视着这位女秘书,秘书的一举一动都会影响到他们!

 

我们先来看第一个问题,仔细分析一下大多数人都会写出如下代码:

class Heater
{
private:
	signed int temperature;
public:

	//热水机烧水
	void BoilWater()
	{
		for(int i=0;i<=100;++i)
		{
			temperature = i;
			if(temperature == 97)
			{
				ShowMSG();
				MakeAlert();
			}
		}
	}
	//显示屏显示
	void ShowMSG()
	{
		cout<<"谁快开了,当前温度:"<<temperature<<",别再烧了"<<endl;
	}
	//警报器发出警报
	void MakeAlert()
	{
		cout<<"Alarm:嘀嘀嘀,水已经"<<temperature<<"度了"<<endl;
	}
};

这样的设计虽然可以达到目的,但是方式不太好,我们知道也许烧水器,显示屏和警报器不一定是同一个厂家生产的,所以我们应该把他们分割成几个类,代码如下:

 

//烧水器(被观察者)
class Heater
{
private:
	signed int temperature;
public:

	//热水机烧水
	void BoilWater()
	{
		for(int i=0;i<=100;++i)
		{
			temperature = i;
			if(temperature == 97)
			{
				//向监听他的两个类发出信息
			}
		}
	}
	
};
//显示屏类(观察着)
class show
{
public:
	void ShowMSG(int param)
	{
		cout<<"谁快开了,当前温度:"<<param<<",别再烧了"<<endl;
	}
};

//警报器类(观察着)
class alarm
{
public:
	void MakeAlert(int param)
	{
		cout<<"Alarm:嘀嘀嘀,水已经"<<temperature<<"度了"<<endl;
	}
}

如果像上面的设计,显示屏类和警报器类都在监督着烧水器的温度,当达到97度的时候,烧水器就会像他的两个观察着发出信息,一边执行必要的操作,可是在C++不像C#有委托和事件处理,所以在C++中需要用到多态的方式,利用vector来操作消息处理,相信这个例子已经很形象的讲述了观察者模式了,接下来让我们具体实现第二个例子

 

 

例子结构如下:

IObservable,被观察者接口

CmishuObservable,被观察者秘书

IObserver,观察者接口

CCoderBObserver,观察者程序员B

CCoderAObserver观察者程序员A

class IObservable            //被观察者接口
{
 IObservable() {}
 virtual ~IObservable() {}

 virtual void AddObserver(IObserver *pObserver) = 0;  //所有被观察者都有的操作
    virtual void DeleteObserver(IObserver *pObserver) = 0;
    virtual void NotifyObservers(string context) = 0;

};

class CmishuObservable:public IObservable          //秘书继承并实现了接口的函数
{
private:
 vector<IObserver *> m_ObserverList;            //用于盛装观察者的容器
 typedef vector<IObserver *>::iterator Observer_iter;

public:
 
 virtual void AddObserver(IObserver *pObserver)
 {
  m_ObserverList.push_back(pObserver);        //把观察者加入到容器中
 }
    virtual void DeleteObserver(IObserver *pObserver) //删除观察着
 {
  Observer_iter it = m_ObserverList.begin();
  for(;it!= m_ObserverList.end();++it)
  {
   if(pObserver == *it)    //这里有点处理得不好,不该比指针,权当例子吧
    m_ObserverList.erase(it);
  }
 }

    virtual void NotifyObservers(string context)   //通告观察者,以便执行更新
 {
  Observer_iter it = m_ObserverList.begin();
  for(;it != m_ObserverList.end();++it)
   (*it)->update(context);
 }
 void HaveBreakfast()           //秘书的行为
 {
  cout<<"美女秘书:开始吃饭去了,饿了啦"<<endl;
  this->NotifyObservers(string("开始吃饭去了,饿了啦"));
 }
 void HaveFun()                //秘书的行为
 {
  cout<<"美女秘书:人家好想去玩啊!"<<endl;
  this->NotifyObservers(string("人家好想去玩啊!"));
 }
};


class IObserver              //观察者接口
{
public:
 IObserver() {}
 virtual ~IObserver() {};

 virtual void update(string context) = 0;
};

class CCoderAObserver:public IObserver   //程序员A继承并实现update
{
private:
 string name;
public:
 CCoderAObserver() 
 {
  name = "Coder A";
 }

 virtual void update(string context)
 {
  //收到消息:我好想去玩,或者去吃饭
  //执行相应的操作
 }
};

class CCoderBObserver:public IObserver //程序员B并实现update
{
private:
 string name;
public:
 CCoderBObserver() 
 {
  name = "Coder B";
 }

 virtual void update(string context)
 {
  //收到消息:我好想去玩,或者去吃饭
  //执行相应的操作
 }
};


 

 


 

通过上面的例子 应该对观察者模式在C++中如何实现比较了解了,总结一下就是利用多态性+容器来分别调用观察者的update函数!

 

 

 

 


 

 


 

你可能感兴趣的:(设计模式,类,程序员)