行为型设计模式

🎯 行为型设计模式详解

行为型模式关注对象之间的通信、职责划分,以及算法的封装。本文详细介绍观察者模式,并补充策略模式、模板方法模式、责任链模式等常用行为型模式。

一、观察者模式

1.1 定义与应用场景

核心思想:如果一个对象的状态发生改变,某些与它相关的对象也要随之做出相应的改变。

观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

角色说明

角色 说明
Subject(主题/被观察者) 维护观察者列表,状态变化时通知所有观察者
Observer(观察者) 定义更新接口,收到通知时执行相应操作
ConcreteSubject(具体主题) 存储具体状态,状态改变时触发通知
ConcreteObserver(具体观察者) 实现更新接口,定义收到通知后的具体行为

1.2 实际案例

📱 微信公众号案例

微信公众号是观察者模式的典型应用:

  • 公众号 = 被观察者(Subject)
  • 订阅用户 = 观察者(Observer)
  • 用户订阅公众号后,公众号发布新消息时,所有订阅用户都能收到通知
cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;

// 观察者接口
class Observer {
public:
  virtual void update(const string& message) = 0;
  virtual ~Observer() = default;
};

// 被观察者接口
class Subject {
public:
  virtual void attach(Observer* observer) = 0;
  virtual void detach(Observer* observer) = 0;
  virtual void notify(const string& message) = 0;
  virtual ~Subject() = default;
};

// 具体被观察者:微信公众号
class WeChatOfficialAccount : public Subject {
private:
  vector<Observer*> observers;
  string accountName;

public:
  WeChatOfficialAccount(const string& name) : accountName(name) {}

  void attach(Observer* observer) override {
    observers.push_back(observer);
    cout << "新用户订阅了公众号: " << accountName << endl;
  }

  void detach(Observer* observer) override {
    for (auto it = observers.begin(); it != observers.end(); ++it) {
      if (*it == observer) {
        observers.erase(it);
        cout << "用户取消订阅公众号: " << accountName << endl;
        break;
      }
    }
  }

  void notify(const string& message) override {
    cout << "\n【" << accountName << "发布新消息】: " << message << endl;
    for (auto observer : observers) {
      observer->update(message);
    }
  }
};

// 具体观察者:微信用户
class WeChatUser : public Observer {
private:
  string userName;

public:
  WeChatUser(const string& name) : userName(name) {}

  void update(const string& message) override {
    cout << "  用户 [" << userName << "] 收到消息: " << message << endl;
  }
};

// 使用示例
int main() {
  // 创建公众号
  WeChatOfficialAccount techBlog("技术周刊");

  // 创建用户
  WeChatUser alice("Alice");
  WeChatUser bob("Bob");
  WeChatUser charlie("Charlie");

  // 用户订阅公众号
  techBlog.attach(&alice);
  techBlog.attach(&bob);
  techBlog.attach(&charlie);

  // 公众号发布消息
  techBlog.notify("设计模式详解系列文章上线了!");

  // 用户取消订阅
  techBlog.detach(&bob);

  // 再次发布消息
  techBlog.notify("新文章:深入理解观察者模式");

  return 0;
}

输出结果

复制代码
新用户订阅了公众号: 技术周刊
新用户订阅了公众号: 技术周刊
新用户订阅了公众号: 技术周刊

【技术周刊发布新消息】: 设计模式详解系列文章上线了!
  用户 [Alice] 收到消息: 设计模式详解系列文章上线了!
  用户 [Bob] 收到消息: 设计模式详解系列文章上线了!
  用户 [Charlie] 收到消息: 设计模式详解系列文章上线了!
用户取消订阅公众号: 技术周刊

【技术周刊发布新消息】: 新文章:深入理解观察者模式
  用户 [Alice] 收到消息: 新文章:深入理解观察者模式
  用户 [Charlie] 收到消息: 新文章:深入理解观察者模式
🌡️ 气象站案例

气象站可以将每天预测到的温度、湿度、气压等以公告的形式发布给各个第三方网站,如果天气数据有更新,要能够实时通知给第三方。

  • 气象局 = 被观察者
  • 第三方网站 = 观察者

1.3 推送模型 vs 拉取模型(补充)

模型 说明 优缺点
推送模型 主题主动将数据传递给观察者 ✅ 优点:观察者直接获得数据 ❌ 缺点:观察者可能不需要所有数据
拉取模型 主题只通知,观察者主动获取数据 ✅ 优点:观察者按需获取 ❌ 缺点:需要多次调用

推送模型示例

cpp 复制代码
void notify(const string& message) {
  for (auto observer : observers) {
    observer->update(message);  // 推送消息
  }
}

拉取模型示例

cpp 复制代码
void notify() {
  for (auto observer : observers) {
    observer->update(this);  // 传递主题引用,观察者自行拉取数据
  }
}

// 观察者拉取数据
void update(Subject* subject) override {
  string data = subject->getData();  // 主动拉取
  // 处理数据
}

参考资料

相关推荐
ximu_polaris3 小时前
设计模式(C++)-结构型模式-享元模式
c++·设计模式·享元模式
geovindu3 小时前
go: Facade Pattern
设计模式·golang·外观模式
旷世奇才李先生5 小时前
React 18\+TypeScript实战: hooks封装与组件设计模式
react.js·设计模式·typescript
白夜11175 小时前
C++设计模式(高内聚,低耦合)
c++·设计模式
ximu_polaris5 小时前
设计模式(C++)-结构型模式-桥接模式
c++·设计模式·桥接模式
楼田莉子5 小时前
仿muduo库的高并发服务器——正则表达式与any类介绍及其简单模拟实现
linux·服务器·c++·学习·设计模式
workflower5 小时前
机器人应用-室外区域巡逻
人工智能·设计模式·机器人·软件工程·软件构建
geovindu7 小时前
go: Flyweight Pattern
开发语言·设计模式·golang·享元模式
志摩凛20 小时前
被产品经理逼疯后,我们重构了移动端上传组件——2026最新成果复盘
设计模式·架构