zoukankan      html  css  js  c++  java
  • 观察者模式

    观察者模式是对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    作用

    将一个系统设计成一系列相互协作的类有一个常见的副作用:需要维护相关对象之间的一致性。

    观察者模式定义一种交互:

    1. 一个对象当自身状态发生改变时,会发出通知,但是并不知道谁是他的接收者,但每个接收者都会接收到通知,这些接受者称为观察者。
    2. 作为对通知的响应,每个观察者都将查询目标状态,然后改变自身的状态以和目标状态进行同步

    使用场景

    1. 使对象封装为独立的改变和使用;
    2. 一个对象改变同时需要改变其它对象,而不知道具体有多少对象需要改变;
    3. 不希望对象是紧耦合的。

    UML

    参与者

    • CSubject: 目标,知道它的观察者,提供注册和删除观察者对象的接口
    • CObserver:观察者,为那些在目标发生改变时需获得通知的对象定义一个更新接口
    • CConcreteSubject:通知所有观察者
    • CConcreteObserver:接受目标的通知

    优缺点

    • 目标和观察者之间松耦合
    • 支持广播通信:CSubject发送的通知不需要指定它的接受者。通知被自动广播给所有已向该目标对象登记的有关对象。
    • 意外的更新:看似无害的操作可能会引起观察者错误的更新。

    代码

    #include <string>
    #include <list>
    
    class CObserver;
    
    class CSubject
    {
    public:
        virtual ~CSubject() {}
        virtual void attach(CObserver* ob) = 0;
        virtual void detach(CObserver* ob) = 0;
        virtual void notify(const std::string & msg) = 0;
    };
    
    class CConcreteSubject : public CSubject
    {
    public:
        CConcreteSubject() = default;
        virtual ~CConcreteSubject() = default;
        void attach(CObserver* ob) override;
        void detach(CObserver* ob) override;
        void notify(const std::string & msg) override;
    
    private:
        std::list<CObserver*> listObserver_;
    };
    
    class CObserver
    {
    public:
        virtual ~CObserver() {}
        virtual void update(const std::string & msg) = 0;
    };
    
    class CConcreteObserver : public CObserver
    {
    public:
        CConcreteObserver() = default;
        CConcreteObserver(const std::string & strName);
        virtual ~CConcreteObserver() = default;
        void update(const std::string & msg) override;
    
    private:
        std::string strName_;
    };
    #include <iostream>
    
    #include "observer.h"
    
    
    void CConcreteSubject::attach(CObserver *ob)
    {
        listObserver_.push_back(ob);
    }
    
    void CConcreteSubject::detach(CObserver *ob)
    {
        listObserver_.remove(ob);
    }
    
    void CConcreteSubject::notify(const std::string & msg)
    {
        for (CObserver * ob : listObserver_)
        {
            ob->update(msg);
        }
    }
    
    
    CConcreteObserver::CConcreteObserver(const std::string & strName) : strName_(strName) {}
    
    void CConcreteObserver::update(const std::string &msg)
    {
        std::cout << this->strName_ << " get message: " << msg << std::endl;
    }
    #include "observer.h"
    
    int main()
    {
        CConcreteObserver a("jack ma");
        CConcreteObserver b("pony ma");
        CConcreteObserver c("robin li");
        CConcreteObserver d("jobs");
        CConcreteObserver e("gates");
    
        CConcreteSubject obj;
        obj.attach(dynamic_cast<CObserver*>(&a));
        obj.attach(dynamic_cast<CObserver*>(&b));
        obj.attach(dynamic_cast<CObserver*>(&c));
        obj.attach(dynamic_cast<CObserver*>(&d));
        obj.attach(dynamic_cast<CObserver*>(&e));
    
        obj.notify("hello");
    
        return 0;
    }
  • 相关阅读:
    Java Web工作原理
    Java——入门“HelloWorld”
    Java——介绍
    vscode给 vue 项目 添加 eslint 验证提示遇到的细节问题
    使用全局变量,当多个线程同时修改静态属性第一季
    自编验证码图片识别程序 自定义的FloodFill函数
    nginx卸载ssl django明文
    nginx 7层全转发
    JAVA Socket入门详解(基本用法与代码实现)
    小白进入公司究竟有哪些不同?学生一定要看!
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/10248871.html
Copyright © 2011-2022 走看看