[置顶] 观察者模式及如何通过消息机制(观察者模式)实现模块间解耦
2018-03-06 11:27
459 查看
1、讲一下什么是观察者模式
什么是观察者模式呢,观察者模式又叫做订阅发布模式,类似这样的例子生活里随处可见,比如公众号,比如微博关注的功能,这都是订阅发布模式,我们对一个公众号感兴趣,就会去关注一个公众号,这个公众号有了什么新的文章,新的内容,就会推送给所有关注了这个公众号的微信号,如果某一天我们对这个公众号不再感兴趣,我们就可以取消对它的关注,后面这个公众号再有什么新的内容,也不会再推送给我们,不会再提醒我们。下面通过代码的形式,实现一个简单的订阅发布模式
第一版
class Subject { public: void registerObserver (CatObserver * a); void removeObserver (CatObserver * a); notifyAll(); private: std::vector< CatObserver *> accounts; }; class CatObserver { void update(); }
这个版本的问题很明显就是没有扩展性,就像我上次讲开闭原则
说的,Subject模块依赖了具体的CatObserver类,后面如果想扩展,让一个DogObserver也可以订阅Subject的主题,那这样的设计就没办法实现了。
第二版
class Subject { public: void registerObserver (Observer * a); void removeObserver (CatObserver * a); notifyAll(); private: std::vector< Observer *> accounts; }; class Observer { virtual void update() = 0; } class CatObserver : public Observer { virtual void update() override { //cat observer update }; } class DogObserver : public Observer { virtual void update() override { //dog observer update }; } class DuckObserver : public Observer { virtual void update() override { //duck observer update }; }
第二版我们让Subject不再依赖一个具体的类,而是依赖一个接口,主题不再需要知道观察者具体类是谁,做了些什么和其他的任何细节,任何时候我们都可以增加新的观察者,因为Sbuject唯一依赖的东西就是一个实现Observer接口的对象列表,所以我们可以随时增加观察者。事实上,再运行时我们可以用新的观察者取代现有的观察者,主题也会收到任何影响。同样的,也可以再任何时候删除某些观察者。
改变主题或者观察者任何其中一方,都不会影响另一方。因为两者是送耦合的,所以只要他们的接口仍被遵循,我们就可以自由的改变他们。送耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的相互依赖降到了最低,这就是松耦合的威力。
2、如何通过观察者模式实现模块的解耦
我们都知道,消息机制一直是软件开发中减少模块之间耦合的标准方式,那消息机制其实就是通过观察者模式实现的,下面我们举一个简单的例子,看看是如何通过消息,减少类 A 和类 B之间的耦合度的。下面是传统的方法,实现 A 对 B 类的某个方法的调用,不使用消息机制的传统方法,A 需要持有 B 的对象,并且 A 要知道所要调用的B的方法,这样 A 和 B 就强耦合在了一起,一旦 B 类发生变化,A 类就可能要重新编译,而且如果 doSomethingBSpecial 这个方法需要改名,或者修改参数,A 类就也需要修改,这样的依赖关系就带来了诸多的不便。
#include "stdafx.h" #include <vector> #include <iostream> //不使用消息机制的传统方法,A 需要持有 B 的对象,并且 A 要知道所要调用的B的方法 //这样A 和 B就强耦合在了一起,一旦 B 类发生变化,A 类就可能要重新编译,而且如果 //doSomethingBSpecial这个方法需要改名,或者修改参数,A 类就也需要修改,这样的 //依赖关系就带来了诸多的不便。 class B { public: void doSomethingBSpecial() { //B 做一些事情 std::cout << "B do something..." << std::endl; } }; class A { public: A(B* b) :m_b(b){} void doSomethingASpecial() { //在这个方法中,会调用B 的 doSomethingBSpecial m_b->doSomethingBSpecial(); } private: B* m_b; }; int _tmain(int argc, _TCHAR* argv[]) { A a(new B()); a.doSomethingASpecial(); return 0; }
下面使用消息机制实现同样的调用,这样 A 就不需要引用 B 的对象,同时 A 也不需要知道 B 的方法,实现了 A 类 和 B 类的解耦。
下面简易的实现了一个的消息处理器,只具备简易的注册,删除和触发事件的功能,在客户的代码中,把 B 的对象注册到消息处理器,使 B 可以处理 doSomethingASpecial 这个消息,然后在 A 类需要调用 B 的方法的地方, 可以直接用消息处理器处理 doSomethingASpecial 这个消息,MsgMgr::handle(“doSomethingASpecial”) 这样调用以后,所有注册过 doSomethingASpecial 这个消息的对象(包括 B 对象),都会接受并且处理这个消息,B 对象的 handle 方法就会被调用,然后在这个方法里就可以去调用 B 的 doSomethingBSpecial 方法,这样就实现了 A 对 B类的 doSomethingBSpecial 方法的调用, 去掉了 A 和 B 之间的耦合依赖关系。
#include "stdafx.h" #include <vector> #include <iostream> #include <map> #include <string> //使用消息机制,A 就不需要持有 B 的对象, //消息接受者接口 class MsgReceiver { public: virtual void handle() = 0; }; //这里实现一个简易的消息处理器,只具备简易的,注册,删除,和触发事件的功能 static std::map<std::string, MsgReceiver*> m_allMsgRecevers; class MsgMgr { public: static void addReceiver(std::string msg, MsgReceiver* receiver) { m_allMsgRecevers.emplace(msg, receiver); } static void removeReceiver(std::string msg) { m_allMsgRecevers.erase(msg); } static void handle(std::string msg) { m_allMsgRecevers.at(msg)->handle(); } }; class A { public: void doSomethingASpecial() { //这里如果想调用 B 的 doSomethingBSpecial 方法 //可以直接用消息处理器处理 doSomethingASpecial 这个消息 //因为 B 已经注册声明过可以处理 doSomethingASpecial 这个消息 //MsgMgr::handle("doSomethingASpecial") 这样调用以后,所有 //注册过 doSomethingASpecial 这个消息的对象,都会接受并且处理这个消息 //这样就去掉了A 和 B之间的耦合依赖关系 MsgMgr::handle("doSomethingASpecial"); } }; class B : public MsgReceiver { public: void doSomethingBSpecial() { //B 做一些事情 std::cout << "B do something..." << std::endl; } virtual void handle() override { doSomethingBSpecial(); } }; int _tmain(int argc, _TCHAR* argv[]) { A a; B* b = new B; //这里把 B 的对象注册到消息处理器,使 B 可以处理 doSomethingASpecial 这个消息 MsgMgr::addReceiver("doSomethingASpecial", b); a.doSomethingASpecial(); return 0; }
相关文章推荐
- 消息机制简单实现模块间解耦
- 设计模式——行为型设计模之借助观察者模式(Observer Pattern)实现模块之间的解耦(四)
- Unity如何实现网络通讯(三):观察者模式以及在网络模块的应用
- 设计模式——行为型模式之通过中介者模式(Mediator Pattern)实现各模块之间的解耦(二)
- 利用消息机制实现.NET AOP(面向方面编程)--通过RealProxy实现
- 如何实现基于消息安全验证机制下的username身份验证过程
- 事件机制 -- 典型观察者模式 js实现
- UI与逻辑的关系、主线程与工作线程的通讯及对观察者模式、消息总线机制的思考
- JAVA动态模块的设计实现以及如何通过newInstance()来创建带参的构造类实例
- iOS开发如何实现消息推送机制
- Ogre源码剖析:如何实现低耦合的类间消息传递机制
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- iOS开发如何实现消息推送机制
- iOS开发如何实现消息推送机制
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- 通过Cache机制实现通用的配置管理模块
- 结合Msg Ack机制和纯Msg的Web Service调用方法实现消息到达主动通知模式
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- 通过Cache机制实现通用的配置管理模块(含源码)