观察者模式及如何通过消息机制(观察者模式)实现模块间解耦

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;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值