观察者模式(Observer)

这篇具有很好参考价值的文章主要介绍了观察者模式(Observer)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

别名

  • 事件订阅者者(Event-Subscriber)
  • 监听者(Listener)

定义

观察者是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。

前言

1. 问题

假如你有两种类型的对象:“顾客”和“商店”。顾客对某个特定品牌的产品非常感兴趣(例如最新型号的 iPhone 手机),而该产品很快将会在商店里出售

  • 一方面顾客可以每天来商店看看产品是否到货。但如果商品尚未到货时,绝大多数来到商店的顾客都会空手而归。
  • 另一方面,每次新产品到货时,商店可以向所有顾客发送邮件(可能会被视为垃圾邮件)。这样,部分顾客就无需反复前往商店了,但也可能会惹恼对新产品没有兴趣的其他顾客。

观察者模式(Observer),设计 模式,观察者模式

我们似乎遇到了一个矛盾:要么让顾客浪费时间检查产品是否到货,要么让商店浪费资源去通知没有需求的顾客。

2. 解决方案

拥有一些值得关注的状态的对象通常被称为目标,由于它要将自身的状态改变通知给其他对象,我们也将其称为发布者(publisher)。所有希望关注发布者状态变化的其他对象被称为订阅者(subscribers)。

观察者模式建议你为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者事件流。不要害怕!这并不像听上去那么复杂。实际上,该机制包括

  1. 一个用于存储订阅者对象引用的列表成员变量。
  2. 几个用于添加或删除该列表中订阅者的公有方法。

观察者模式(Observer),设计 模式,观察者模式

现在,无论何时发生了重要的发布者事件,它都要遍历订阅者并调用其对象的特定通知方法。

实际应用中可能会有十几个不同的订阅者类跟踪着同一个发布者类的事件, 你不会希望发布者与所有这些类相耦合的。 此外如果他人会使用发布者类,那么你甚至可能会对其中的一些类一无所知。因此,所有订阅者都必须实现同样的接口,发布者仅通过该接口与订阅者交互。接口中必须声明通知方法及其参数,这样发布者在发出通知时还能传递一些上下文数据。

观察者模式(Observer),设计 模式,观察者模式

如果你的应用中有多个不同类型的发布者,且希望订阅者可兼容所有发布者,那么你甚至可以进一步让所有订阅者遵循同样的接口。该接口仅需描述几个订阅方法即可。这样订阅者就能在不与具体发布者类耦合的情况下通过接口观察发布者的状态。

结构

观察者模式(Observer),设计 模式,观察者模式

  1. 发布者(Publisher)会向其他对象发送值得关注的事件。事件会在发布者自身状态改变或执行特定行为后发生。发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架。
  2. 当新事件发生时,发送者会遍历订阅列表并调用每个订阅者对象的通知方法。该方法是在订阅者接口中声明的。
  3. 订阅者(Subscriber)接口声明了通知接口。 在绝大多数情况下,该接口仅包含一个 update方法。该方法可以拥有多个参数,使发布者能在更新时传递事件的详细信息。
  4. 具体订阅者(Concrete Subscribers)可以执行一些操作来回应发布者的通知。 所有具体订阅者类都实现了同样的接口,因此发布者不需要与具体类相耦合。
  5. 订阅者通常需要一些上下文信息来正确地处理更新。 因此,发布者通常会将一些上下文数据作为通知方法的参数进行传递。发布者也可将自身作为参数进行传递,使订阅者直接获取所需的数据。
  6. 客户端(Client)会分别创建发布者和订阅者对象,然后为订阅者注册发布者更新。

适用场景

  • 当一个对象状态的改变需要改变其他对象,或实际对象是事先未知的或动态变化的时,可使用观察者模式。

当你使用图形用户界面类时通常会遇到一个问题。比如,你创建了自定义按钮类并允许客户端在按钮中注入自定义代码,这样当用户按下按钮时就会触发这些代码。观察者模式允许任何实现了订阅者接口的对象订阅发布者对象的事件通知。你可在按钮中添加订阅机制,允许客户端通过自定义订阅类注入自定义代码。

  • 当应用中的一些对象必须观察其他对象时,可使用该模式。但仅能在有限时间内或特定情况下使用。

订阅列表是动态的,因此订阅者可随时加入或离开该列表。

实现方式

  1. 仔细检查你的业务逻辑,试着将其拆分为两个部分:独立于其他代码的核心功能将作为发布者;其他代码则将转化为一组订阅类。
  2. 声明订阅者接口。该接口至少应声明一个 update 方法。
  3. 声明发布者接口并定义一些接口来在列表中添加和删除订阅对象。记住发布者必须仅通过订阅者接口与它们进行交互。
  4. 确定存放实际订阅列表的位置并实现订阅方法。通常所有类型的发布者代码看上去都一样,因此将列表放置在直接扩展自发布者接口的抽象类中是显而易见的。具体发布者会扩展该类从而继承所有的订阅行为。但是,如果你需要在现有的类层次结构中应用该模式,则可以考虑使用组合的方式: 将订阅逻辑放入一个独立的对象,然后让所有实际订阅者使用该对象。
  5. 创建具体发布者类。每次发布者发生了重要事件时都必须通知所有的订阅者。
  6. 在具体订阅者类中实现通知更新的方法。绝大部分订阅者需要一些与事件相关的上下文数据。这些数据可作为通知方法的参数来传递。但还有另一种选择。订阅者接收到通知后直接从通知中获取所有数据。在这种情况下,发布者必须通过更新方法将自身传递出去。另一种不太灵活的方式是通过构造函数将发布者与订阅者永久性地连接起来。
  7. 客户端必须生成所需的全部订阅者,并在相应的发布者处完成注册工作。

优点

  • 开闭原则。 你无需修改发布者代码就能引入新的订阅者类(如果是发布者接口则可轻松引入发布者类)。
  • 你可以在运行时建立对象之间的联系。

缺点

订阅者的通知顺序是随机的。

Publisher.hpp

#ifndef FD172440_394F_4863_9CAE_F8560CE768A8
#define FD172440_394F_4863_9CAE_F8560CE768A8

#include <vector>
#include <iostream>
#include "Subscriber.hpp"

class Cat {
 public:
    // 注册观察者
    void attach(AbstractObserver* observer) {
        observers_.push_back(observer);
    }

    // 注销观察者
    void detach(AbstractObserver* observer) {
        for (auto it = observers_.begin(); it !=observers_.end(); it++) {
            if (*it == observer) {
                observers_.erase(it);
                break;
            }
        }
    }

    void cry() {
        std::cout << "猫叫!" << std::endl;
        for (auto ob : observers_) {
            ob->response();
        }
    }

 private:
    std::vector<AbstractObserver*> observers_;
};

#endif /* FD172440_394F_4863_9CAE_F8560CE768A8 */

Subscriber.hpp

#ifndef CCE3E5F5_BD59_43AE_9BCA_E13909DD792C
#define CCE3E5F5_BD59_43AE_9BCA_E13909DD792C

class AbstractObserver {
    public:
        virtual void response() = 0;
};

#endif /* CCE3E5F5_BD59_43AE_9BCA_E13909DD792C */

ConcreteSubscriber.hpp

#ifndef F648013D_8238_484B_83AC_2D374CD2D65E
#define F648013D_8238_484B_83AC_2D374CD2D65E

#include <iostream>
#include "Subscriber.hpp"

// 具体观察者1: 老鼠
class Mouse : public AbstractObserver {
 public:
    void response() override {
        std::cout << "老鼠逃跑" << std::endl;
    }
};

// 具体观察者2: 狗
class Dog : public AbstractObserver {
 public:
    void response() override {
        std::cout << "狗追猫" << std::endl;
    }
};
#endif /* F648013D_8238_484B_83AC_2D374CD2D65E */

main.cpp文章来源地址https://www.toymoban.com/news/detail-517862.html

#include "Publisher.hpp"
#include "ConcreteSubscriber.hpp"

int main() {
    // 发布者
    Cat cat;

    // 观察者
    Mouse mouse;
    Dog dog;

    // 添加订阅关系
    cat.attach(&mouse);
    cat.attach(&dog);

    // 发布消息
    cat.cry();
    return 0;
}

到了这里,关于观察者模式(Observer)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式——观察者模式(Observer Pattern)+ Spring相关源码

    类型:行为型模式 目的:当一个对象的状态发生改变时,其所有依赖者(观察者)都会收到通知并自动更新。 2.1.1 定义观察者 2.1.2 定义被观察对象 2.1.3 使用 2.2.1 观察者接口Observer 2.2.1 被观察者对象Observable 2.3.1 观察者 2.3.2 被观察者 创建型模式 结构型模式 1、设计模式——

    2024年02月06日
    浏览(37)
  • 【设计模式——学习笔记】23种设计模式——观察者模式Observer(原理讲解+应用场景介绍+案例介绍+Java代码实现)

    有一个天气预报项目,需求如下: 气象站可以将每天测量到的温度、湿度、气压等等以公告的形式发布出去(比如发布到自己的网站或第三方) 需要设计开放型API,便于其他第三方也能接入气象站获取数据 提供温度、气压、湿度的接口 测量数据更新时,要能实时的通知给第三

    2024年02月14日
    浏览(29)
  • 观察者模式(Observer)

    事件订阅者者(Event-Subscriber) 监听者(Listener) 观察者 是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个“观察”该对象的其他对象。 1. 问题 假如你有两种类型的对象 :“顾客”和“商店”。顾客对某个特定品牌的产品非常感兴趣(例如最

    2024年02月12日
    浏览(27)
  • 观察者模式(Observer)

    观察着模式是一种行为设计模式,可以用来定义对象间的一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。 观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者

    2024年02月14日
    浏览(27)
  • Kotlin~Observer观察者模式

    概念 定义一对多的依赖关系,让多个观察者同时监听一个主题对象。 角色介绍 Subject:主题,也称被观察者,它是具有状态的对象维护着一个观察者列表。提供添加、删除和通知观察者的方法。 ConcreteSubject:具体主题,主题的具体实现类,维护观察者列表,状态改变时通知

    2024年02月15日
    浏览(38)
  • 行为型-观察者模式(Observer Pattern)

    详细介绍观察者模式(Observer Pattern),并说明优缺点与使用场景: 观察者模式是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖它的对象都会自动收到通知并更新。该模式包含两个核心角色:被观察者(Subj

    2024年02月15日
    浏览(54)
  • 观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

            观察者设计模式(Observer Design Pattern)是一种行为型设计模式,它定义了一种对象间的一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,通知所有观察者对象,使它们能够自动更新。 主题(Subject):主题是一个抽象类或

    2023年04月24日
    浏览(32)
  • (三)行为模式:7、观察者模式(Observer Pattern)(C++示例)

    目录 1、观察者模式(Observer Pattern)含义 2、观察者模式的UML图学习 3、观察者模式的应用场景 4、观察者模式的优缺点 (1)优点: (2)缺点 5、C++实现观察者模式的实例 1、观察者模式(Observer Pattern)含义 观察者模式(Observer)定义了一种一对多的依赖关系,让多个观察者

    2024年02月09日
    浏览(31)
  • 设计模式——观察者模式

    观察者模式可以分为观察者和被观察者,观察者通过注册到一个被观察者中,也可视为订阅,当被观察者的数据发生改变时,会通知到观察者,观察者可以据此做出反应。 可以类比订阅报纸,报社就是被观察者,订阅者就是观察者,订阅者通过订阅报纸与报社建立联系,而报

    2024年02月15日
    浏览(37)
  • 设计模式---观察者模式

    1,概念         属于行为模式的一种,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一对象主题对象,这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。 在观察者模式中有如下角色: Subject:抽象主题(抽象被观察者),

    2024年02月15日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包