前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php设计模式(十九):观察者模式(Observer)

php设计模式(十九):观察者模式(Observer)

作者头像
陈大剩博客
发布2023-05-22 08:35:21
3740
发布2023-05-22 08:35:21
举报

观察者模式

观察者模式又称为:事件订阅者、监听者、Event-Subscriber、Listener、Observer。观察者是一种行为设计模式,允许定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。

问题

观察者模式是一种发布和订阅模式,我们平常去抢购茅台、Aj、…多少会用到观察者模式。

如我们抢购鞋子(AJ),平常每天去门店看看鞋子是否到货。但如果鞋子尚未到货时,绝大多数来到 门店 的顾客都会空手而归。

另一方面,每次新鞋子到货时,门店可以向所有顾客发送邮件(可能会被视为垃圾邮件)。 这样, 部分顾客就无需反复前往门店了,也可能会惹恼对新鞋子没有兴趣的其他顾客。

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

解决方法

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

我们为发布者类(门店)添加订阅机制,让每个对象(顾客)都能订阅或取消订阅发布者事件流。

该机制包括:

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

结构

Shop: 具体的门店类; Subscriber: 订阅者接口 ; Customer: 具体的 Subscriber 示例中指 顾客 ;

代码示例

具体的门店类(Shop 类)

代码语言:javascript
复制
/**
 * 门店
 */
class Shop
{
    /**
     * 订阅者
     * @var array
     */
    private $subscribers = [];

    /**
     * 添加订阅者
     * @return void
     * @author chendashengpc
     */
    public function attach(Subscriber $subscriber)
    {
        $this->subscribers[$subscriber->name] = $subscriber;
    }

    /**
     * 删除订阅者
     * @return void
     * @author chendashengpc
     */
    public function detach(Subscriber $subscriber)
    {
        if (isset($this->subscribers[$subscriber->name])) {
            unset($this->subscribers[$subscriber->name]);
        }
    }

    /**
     * 提醒
     * @return void
     * @author chendashengpc
     */
    public function notify()
    {
        if (count($this->subscribers) == 0) {
            return;
        }
        foreach ($this->subscribers as $subscriber) {
            $subscriber->update();
        }
    }
}

订阅者接口

代码语言:javascript
复制
abstract class Subscriber
{
    /**
     * @var string 订阅者姓名
     */
    public string $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    abstract public function update();
}

顾客类

代码语言:javascript
复制
class Customer extends Subscriber
{
    public function update()
    {
        echo '我是' . $this->name, ',我马上来门店产看新产品' . PHP_EOL;
    }
}

客户端使用

代码语言:javascript
复制
$shop = new Shop();
$zs = new Customer('张三');
$ls = new Customer('李四');
$ww = new Customer('王五');

$shop->attach($zs);
$shop->attach($ls);
$shop->attach($ww);

$shop->notify();
echo PHP_EOL;
echo '产品不好,李四想退出订阅' . PHP_EOL;
$shop->detach($ls);
$shop->notify();

输出

代码语言:javascript
复制
我是张三,我马上来门店产看新产品
我是李四,我马上来门店产看新产品
我是王五,我马上来门店产看新产品

产品不好,李四想退出订阅
我是张三,我马上来门店产看新产品
我是王五,我马上来门店产看新产品

php 官方已经提供了,请参考:SplObserverSplSubject

UML

UML
UML

优缺点

优点

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

缺点

  • 订阅者的通知顺序是随机的。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 观察者模式
  • 问题
  • 解决方法
  • 结构
  • 代码示例
    • 具体的门店类(Shop 类)
      • 订阅者接口
        • 顾客类
          • 客户端使用
          • UML
          • 优缺点
            • 优点
              • 缺点
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档