1 观察者模式
1.0 需求
两个对象之间存在一种关系:当一个对象的状态变化时,另一个类的状态应该做出相应的变化。
1.1 实现
一个对象变化需要通知另一个对象,轮询是不可能的,只能是显式的通知,也就是说一个对象在状态变化的时候显式的通知另一个对象。显式通知的意思是 调用另一个对象的一个方法。
// 前置声明
class ABChanger;
// 主动观察者基类
// 他会被动的接到通知。
class ABStaff
{
public:
virtual void update(/*可能的参数*/)=0;
void attach(ABChanger* );
private:
ABChanger* Changer;
};
// 具体的不同种类的观察者,对收到的消息做出相应
class Staff1 :public ABStaff
{
//重写 update 表示对手打通知以后会做出的相应
};
class Staff1 :public ABStaff
{
//重写 update 表示对手打通知以后会做出的相应
};
// 被观察的对象,当自己状态改变的时候需要通知观察了自己的对象
class ABChanger
{
public:
void add(ABStaff* );
void remove(ABStaff* );
void update(/*可能的参数*/){
//遍历 list 调用每个 ABStaff 的 update ,达到通知的目的
}
private:
vector<ABStaff*> list;
};
class Changer1:public ABChanger
{
//可能不同的 ABChanger
};
1.2 理解
感觉观察者模式,改名为通知模式更为贴切,因为是当一个类状态改变的时候,自己主动去通知别人。
2 发布订阅模式
2.0 需求
观察者模式,观察者与被观察者之间强耦合。
而订阅发布模式在进行解耦,中间添加一个Centor
发布者(被观察者)当状态改变的时候向Centor发布消息(发布者调用函数,然后将Centor,和消息传入函数,函数内部又会将消息转发给Centor)。Centor的函数又会遍历、通知所有订阅了该消息的观察者(调用其函数)。
2.1 实现
// 前置声明
class ABCentor; // 消息中心:收到Publisher,发来的消息就遍历ABStaff调用其update
class Publisher; // 发布消息,调用 ABCentor 的publish
class ABStaff; // 订阅到 ABCentor,由 ABCentor 调用自己的update
// 主动观察者基类
// 他会被动的接到通知。
class ABStaff
{
public:
virtual void update(/*可能的参数*/) = 0;
void attach(ABCentor *); //订阅相关频道
private:
ABCentor *centor;
};
// 具体的不同种类的观察者,对收到的消息做出相应
class Staff1 : public ABStaff
{
//重写 update 表示对手打通知以后会做出的相应
};
class Staff1 : public ABStaff
{
//重写 update 表示对手打通知以后会做出的相应
};
// 被观察的对象,当自己状态改变的时候需要通知观察了自己的对象
class ABCentor
{
public:
void add(ABStaff *);
void remove(ABStaff *);
void publish(Msg)
{
//遍历所有的订阅者,调用订阅者的 update();
}
private:
vector<ABStaff *> list;
};
class Centor1 : public ABCentor
{
//可能不同的 ABCentor
};
// Publisher 也可能存在继承
class Publisher
{
public:
// 消息转发给 ABCentor
void publish(ABCentor *centor, Msg msg)
{
centor->publish(msg);
}
}
3 总结
本质上没有区别,只是发布订阅模式,将发布者和订阅者解耦了。
另外,真的这种模式叫做通知模式更好,因为是观察者并没有观察观察者,而是被观察者显式的通知了观察者。