首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >设计模式(一) 观察者模式

设计模式(一) 观察者模式

原创
作者头像
金莲与饼皆失
发布2025-09-10 08:53:41
发布2025-09-10 08:53:41
12400
代码可运行
举报
文章被收录于专栏:Linux进程与线程Linux进程与线程
运行总次数:0
代码可运行

一、概述

在GOF的《设计模式:可复用面向对象软件的基础》一书中对观察者模式是这样定义的:定义对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也成为发布-订阅(publish-subscribe)。

二、类图

三、示例代码

代码语言:cpp
代码运行次数:0
运行
复制
#include <iostream>
#include <string>
#include <list>
#include <memory>
using std::unique_ptr;
using std::list;
using std::string;
using std::cout;
using std::endl;

// 观察者基类
class Observer{
public:
    // 获取状态更新
    virtual void update(int status) = 0;
    // 虚析构函数
    virtual ~Observer(){};
};

class ConcreteObserverA:public Observer{
public:
    ConcreteObserverA(const string name)
    :_name(name)
    {
        // 构造函数
    }
    virtual void update(int status) override{
        cout << "ConcreteObserverA name is : " << _name << " status:" << status << endl;
    }
private:
    string _name;
};

class ConcreteObserverB:public Observer{
public:
    ConcreteObserverB(const string name)
    :_name(name)
    {
        // 构造函数
    }
    virtual void update(int status) override{
        cout << "ConcreteObserverB name is : " << _name << " status:" << status << endl;
    }
private:
    string _name;
};

// 主题的抽象基类,所有番剧的基类
class Subject{
public:
    // 添加观察者
    virtual void attach(Observer * pob) = 0;
    // 删除观察者
    virtual void detach(Observer * pob) = 0;
    // 通知观察者
    virtual void notify() = 0;
    virtual ~Subject(){};
};

// 具体的主题,假设是具体的番剧
class ConcreteSubject:public Subject{
public:
    virtual void attach(Observer * pob) override{
        if(pob){
            _listOb.push_back(pob);
        }
    }
    virtual void detach(Observer * pob) override{
        if(pob){
            _listOb.remove(pob);
        }
    }
    virtual void notify() override{
        for(auto & ele:_listOb){
            ele->update(_status); // 实现动态
        }
    }
    void setstatus(int sta){
        _status = sta;
    }
    int getstatus(){
        return _status;
    }
private:
    // 存放观察者的数据结构
    list<Observer *> _listOb;
    // 状态
    int _status;
};

void test(void){
    unique_ptr<Observer> ob1(new ConcreteObserverA("tianming"));
    unique_ptr<Observer> ob2(new ConcreteObserverB("lili"));
    // 创建主题对象
    unique_ptr<ConcreteSubject> csub(new ConcreteSubject());
    // 将观察者添加到主题的数据结构中进行存储
    csub->attach(ob1.get());
    csub->attach(ob2.get());
    // 当主题状态发生变更
    csub->setstatus(888);
    // 马上发通知
    csub->notify();
    cout << endl;
    // 当某个观察者不再关注该番剧
    csub->detach(ob2.get());
    // 再次变化
    csub->setstatus(999);
    // 立马通知
    csub->notify();

}

int main(int argc, char * argv[]){
    test();
    return 0;
}

四、优缺点

优点:

观察者和被观察者是抽象耦合的;

建立一套触发机制。

缺点:

如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;

如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃;

观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

五、应用场景

  • 一个抽象模型有两个方面,其中一个方面发依赖于另外一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用;
  • 一个对象的改变将导致其它一个或多个对象发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度;
  • 一个对象必须通知其他对象,而并不知道这些对象是谁;
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述
  • 二、类图
  • 三、示例代码
  • 四、优缺点
  • 五、应用场景
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档