观察者模式

简介: 观察者模式是一种行为型设计模式,用于定义对象间的一对多依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会自动收到通知并更新。该模式主要用于实现发布-订阅机制。核心角色包括主题(Subject)、观察者(Observer)、具体主题(Concrete Subject)和具体观察者(Concrete Observer)。优点包括低耦合、动态添加观察者和自动更新,但也有可能引起过多更新、不适合同步通知和可能造成内存泄漏等缺点。适用于气象站数据更新、股票价格监控和用户界面组件更新等场景。

观察者模式详解

定义

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会自动收到通知并更新。这种模式主要用于实现发布-订阅机制。


观察者模式的结构

核心角色

  1. 主题(Subject):被观察的对象,包含多个观察者。它提供注册、注销和通知观察者的方法。
  2. 观察者(Observer):依赖于主题的对象,当主题发生变化时,观察者会收到通知并更新自己的状态。
  3. 具体主题(Concrete Subject):实现了通知机制的具体对象,它在状态变化时通知所有注册的观察者。
  4. 具体观察者(Concrete Observer):每个观察者响应主题的状态变化,并进行相应的操作。

使用案例

案例 1:气象站数据更新

多个显示设备(例如手机、电视、天气站)都订阅气象站,当气象数据更新时,它们自动显示最新信息。

案例 2:股票价格监控

多个投资者或应用程序监控股票价格,当价格变化时,所有订阅者会收到通知并做出反应。

案例 3:用户界面组件更新

UI组件(如按钮、文本框)观察模型数据,当模型数据变化时,UI组件会自动更新,保持一致。


观察者模式的优缺点

优点

  1. 低耦合:观察者与主题之间是松耦合的,观察者并不依赖于主题的具体实现。
  2. 动态添加观察者:可以在运行时动态添加或移除观察者,灵活性高。
  3. 自动更新:当主题状态发生变化时,所有观察者会自动得到更新通知。

缺点

  1. 可能引起过多更新:如果观察者过多,频繁的通知可能带来性能问题。
  2. 不适合同步通知:如果观察者之间有较强依赖关系,直接通知可能导致不一致性。
  3. 可能会造成内存泄漏:如果没有正确管理观察者的生命周期,可能会导致观察者未能正确注销。

观察者模式的结构图

观察者模式的实现

C++ 实现

#include <iostream>
#include <vector>
#include <memory>

// 抽象观察者
class Observer {
public:
   virtual void Update(int state) = 0;
   virtual ~Observer() = default;
};

// 具体观察者
class ConcreteObserver : public Observer {
private:
   int state;
public:
   void Update(int newState) override {
       state = newState;
       std::cout << "Observer state updated to: " << state << std::endl;
   }
};

// 抽象主题
class Subject {
public:
   virtual void Attach(std::shared_ptr<Observer> observer) = 0;
   virtual void Detach(std::shared_ptr<Observer> observer) = 0;
   virtual void Notify() = 0;
   virtual ~Subject() = default;
};

// 具体主题
class ConcreteSubject : public Subject {
private:
   std::vector<std::shared_ptr<Observer>> observers;
   int state;
public:
   void Attach(std::shared_ptr<Observer> observer) override {
       observers.push_back(observer);
   }

   void Detach(std::shared_ptr<Observer> observer) override {
       observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
   }

   void Notify() override {
       for (auto& observer : observers) {
           observer->Update(state);
       }
   }

   void SetState(int newState) {
       state = newState;
       Notify();
   }
};

// 客户端代码
int main() {
   auto subject = std::make_shared<ConcreteSubject>();
   auto observer1 = std::make_shared<ConcreteObserver>();
   auto observer2 = std::make_shared<ConcreteObserver>();

   subject->Attach(observer1);
   subject->Attach(observer2);

   subject->SetState(1); // 更新状态并通知观察者

   return 0;
}


C# 实现

using System;
using System.Collections.Generic;

// 抽象观察者
public interface IObserver {
   void Update(int state);
}

// 具体观察者
public class ConcreteObserver : IObserver {
   private int state;
   public void Update(int newState) {
       state = newState;
       Console.WriteLine($"Observer state updated to: {state}");
   }
}

// 抽象主题
public interface ISubject {
   void Attach(IObserver observer);
   void Detach(IObserver observer);
   void Notify();
}

// 具体主题
public class ConcreteSubject : ISubject {
   private List<IObserver> observers = new List<IObserver>();
   private int state;

   public void Attach(IObserver observer) {
       observers.Add(observer);
   }

   public void Detach(IObserver observer) {
       observers.Remove(observer);
   }

   public void Notify() {
       foreach (var observer in observers) {
           observer.Update(state);
       }
   }

   public void SetState(int newState) {
       state = newState;
       Notify();
   }
}

// 客户端代码
class Program {
   static void Main(string[] args) {
       ConcreteSubject subject = new ConcreteSubject();
       ConcreteObserver observer1 = new ConcreteObserver();
       ConcreteObserver observer2 = new ConcreteObserver();

       subject.Attach(observer1);
       subject.Attach(observer2);

       subject.SetState(1);  // 更新状态并通知观察者
   }
}


观察者模式的优缺点对比

特性 优点 缺点
松耦合 观察者和主题之间解耦,可以动态添加观察者 如果观察者过多,可能导致性能下降
灵活性 允许主题对象在运行时增加或删除观察者 不适合复杂的同步通知
自动更新 主题状态变化时自动通知观察者 如果没有正确管理生命周期,可能会导致内存泄漏

总结

观察者模式是一种非常重要的行为型设计模式,它非常适用于需要在某些事件发生时通知多个对象的场景。它具有高灵活性和可扩展性,在许多系统中都可以找到它的身影,尤其是在事件驱动和消息发布-订阅系统中。使用观察者模式时,需注意管理观察者的生命周期,并避免频繁的状态更新导致性能问题。

目录
相关文章
|
人工智能
Gemini 1.5:最高支持100万tokens,超长上下文有什么用?
【2月更文挑战第2天】Gemini 1.5:最高支持100万tokens,超长上下文有什么用?
604 1
Gemini 1.5:最高支持100万tokens,超长上下文有什么用?
|
10月前
|
设计模式 C# C++
责任链模式(Chain of Responsibility Pattern)
责任链模式是一种行为型设计模式,允许多个对象按顺序处理请求,直到某个对象处理为止。适用于多个对象可能处理同一请求的场景,如请假审批流程。优点是灵活性高、降低耦合,但责任链过长可能影响性能。
300 3
|
10月前
|
XML 设计模式 JSON
模板方法模式(Template Method Pattern)
模板方法模式是一种行为型设计模式,定义一个操作中的算法骨架,将某些步骤的实现延迟到子类。子类可以在不改变算法结构的情况下重新定义算法的某些步骤。适用于多个类有相似操作流程且部分步骤需要定制的场景。优点包括高复用性、扩展性强和清晰明确;缺点是灵活性降低和可能引入性能开销。示例包括文件解析和策略模式的对比。
156 3
模板方法模式(Template Method Pattern)
|
10月前
|
存储 设计模式 算法
命令模式(Command Pattern)
命令模式是一种行为型设计模式,将请求封装为对象,实现参数化请求、支持撤销操作和记录日志。适用于需要解耦发送者和接收者的场景,如智能家居系统中的遥控器控制电灯开关并支持撤销功能。优点包括解耦、支持撤销与恢复操作,但过度使用会增加系统复杂度。
168 7
|
10月前
|
设计模式 C# C++
建造者模式详解
建造者模式是一种创建型设计模式,通过将对象的构造与表示分离,使得同样的构建过程可以创建不同的对象。它适用于复杂对象的构建,如汽车制造、软件配置生成等场景。该模式的核心角色包括抽象建造者、具体建造者、产品和指挥者。优点包括解耦构造和表示、代码复用性强、易于扩展;缺点是增加代码复杂度,对产品组成部分有依赖。
246 3
|
10月前
|
设计模式 监控 数据库
代理模式(Proxy Pattern)
代理模式(Proxy Pattern)是一种设计模式,通过一个中间对象(代理)来间接访问目标对象,以控制访问权限或添加额外功能。常见的代理类型包括远程代理、虚拟代理、保护代理和智能引用代理。代理模式常用于延迟加载、权限控制、日志记录等场景,能够提高系统的灵活性和安全性。
406 3
|
10月前
|
设计模式 IDE 数据可视化
UML中类图的介绍与使用
类图是 UML 中用于展示系统静态结构的重要工具,包括类、接口及其关系。类图有助于系统可视化、团队沟通、发现设计问题、文档化系统和辅助开发工具。类图的三大元素是类、接口和关系,其中关系又细分为关联、聚合、组合、继承、实现和依赖。类图在设计模式学习和实际开发中非常重要,许多现代 IDE 都支持从类图生成代码或从代码生成类图。
490 2
|
10月前
|
设计模式 数据库 C#
外观模式(Facade Pattern)
外观模式(Facade Pattern)是一种结构型设计模式,为子系统中的一组接口提供一个一致的接口。它通过一个高层接口简化子系统的复杂性,使客户端更容易使用。外观模式的核心角色包括外观(Facade)和子系统(Subsystems),主要优点是降低复杂性和松耦合,适用于简化接口、分层设计和遗留代码集成等场景。
137 2
|
10月前
|
设计模式 算法 定位技术
策略模式(Strategy Pattern)
策略模式(Strategy Pattern)是一种行为型设计模式,允许在运行时选择算法或行为,而不是在编译时确定。通过将具体算法封装成独立的类,并通过统一接口与客户端交互,实现算法的动态替换,避免代码重复和复杂条件语句。适用于支付方式切换、导航路径选择等场景。
294 1
|
10月前
|
设计模式 C# C++
适配器模式(Adapter Pattern)
适配器模式是一种结构型设计模式,通过将一个类的接口转换为客户期望的另一个接口,使原本接口不兼容的类可以一起工作。它包括目标接口、适配者和适配器三个核心角色。适配器模式常用于解决旧系统兼容性问题、第三方库整合和统一接口等场景。该模式有类适配器和对象适配器两种实现方式,分别通过继承和组合实现。适配器模式的优点包括提高兼容性、遵循开闭原则和灵活性高,但也存在适配器数量增加导致复杂性和可能影响性能的缺点。
349 1
下一篇
oss教程