观察者模式(Observer)定义了对象间一对多的联系。当一个对象的状态发生变化时,所有与它有联系的观察者对象都会得到通知。观察者模式将被观察的目标和观察者解耦,一个目标可以有任意多的观察者,观察者也可以观察任意多的目标,构成复杂的联系,而每个观察者都不知道其他观察者的存在。
这里我就不列出那么多正式化的UML图了,那些是书本上的事,如果要详细学设计模式,推荐Gof的大话设计模式
我们在这里举两个例子来说明
第一:烧水瓶热水时候,当烧到97度的时候,显示屏会收到消息,然后再屏幕上显示当前温度,声控器会发出声音,提示报警!
第二:某软件公司突然来了一个性感的女秘书,程序员A和程序员B这两个钓丝按耐不住了,密切注视着这位女秘书,秘书的一举一动都会影响到他们!
我们先来看第一个问题,仔细分析一下大多数人都会写出如下代码:
[cpp]
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<<"谁快开了,当前温度:"<
//警报器发出警报
void MakeAlert()
{
cout<<"Alarm:嘀嘀嘀,水已经"<
};
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<<"谁快开了,当前温度:"<
//警报器发出警报
void MakeAlert()
{
cout<<"Alarm:嘀嘀嘀,水已经"<
};
这样的设计虽然可以达到目的,但是方式不太好,我们知道也许烧水器,显示屏和警报器不一定是同一个厂家生产的,所以我们应该把他们分割成几个类,代码如下:
[cpp]
//烧水器(被观察者)
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<<"谁快开了,当前温度:"< }
};
//警报器类(观察着)
class alarm
{
public:
void MakeAlert(int param)
{
cout<<"Alarm:嘀嘀嘀,水已经"<
}
//烧水器(被观察者)
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<<"谁快开了,当前温度:"< }
};
//警报器类(观察着)
class alarm
{
public:
void MakeAlert(int param)
{
cout<<"Alarm:嘀嘀嘀,水已经"<
}
如果像上面的设计,显示屏类和警报器类都在监督着烧水器的温度,当达到97度的时候,烧水器就会像他的两个观察着发出信息,一边执行必要的操作,可是在C++不像C#有委托和事件处理,所以在C++中需要用到多态的方式,利用vector来操作消息处理,相信这个例子已经很形象的讲述了观察者模式了,接下来让我们具体实现第二个例子
例子结构如下:
IObservable,被观察者接口
CmishuObservable,被观察者秘书
IObserver,观察者接口
CCoderBObserver,观察者程序员B
CCoderAObserver观察者程序员A
[cpp] view plaincopyprint
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
typedef vector
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(;