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 总结
本质上没有区别,只是发布订阅模式,将发布者和订阅者解耦了。
另外,真的这种模式叫做通知模式更好,因为是观察者并没有观察观察者,而是被观察者显式的通知了观察者。