搜索

查看: 3207|回复: 11

[PHP] PHP设计模式中观察者模式详解

[复制链接]
发表于 2023-5-4 17:06:10 | 显示全部楼层 |阅读模式
Editor 2023-5-4 17:06:10 3207 11 看全部
目录
  • 简介
  • 适用场景
  • 缺点
  • 补充
  • 代码(自定义实现)
    简介
    观察者模式是行为型模式的一种,定义了对象间一对多的关系。当对象的状态发生变化时候,依赖于它的对象会得到通知。

    适用场景
    类似触发钩子事件,可做消息通知、框架底层监听。
    一个对象的改变会导致一个或多个对象发生改变,方便扩展的写法。
    优点
    方便扩展,降低耦合,统一触发规则。当需要新增或者删除一个观察者的时候,只需要增加观察者就行。

    缺点
    相比于不用观察者而是直接依赖某些类,增加代码的复杂度。
    如果观察者者被观察者互相依赖,有产生死循环的可能。

    补充
    需要理清楚观察者和被观察者是谁,观察者可以理解为被动受到通知的对象。被观察者是主动发送通知的对象。
    固定的套路,被观察者至少需要一个添加观察者的方法和一个通知观察者的方法用来确定身份和发送通知(一般有三个,多一个删除观察者的方法),观察者至少需要一个更新的方法用于接收被观察者的通知。

    代码(自定义实现)
    //假设用户成功购买商品后需要发送邮件和短信通知
    class Order {
        private $observers = [];
        //添加观察者
        public function attach($type, $observer) {
            $this->observers[$type] = $observer;
        }
        //对每个观察者进行通知
        public function notify() {
            if ($this->observers == []) {
                return null;
            }
            foreach ($this->observers as $every_observer) {
                (new $every_observer)->update($this);
            }
        }
        //购买商品,触发通知
        public function buyGoods() {
            //todo 订单操作
            echo '商品购买完成' . PHP_EOL;
            $this->notify();
        }
    }
    class Mail {
        public function update($observer) {
            echo '发送电子邮件' . PHP_EOL;
        }
    }
    class Sms {
        public function update($observer) {
            echo '发送短信' . PHP_EOL;
        }
    }
    $order = new Order();
    //添加观察者
    $order->attach('mail', Mail::class);
    $order->attach('sms', Sms::class);
    $order->buyGoods();
    代码(基于SPL实现)
    SPL(Standard PHP Library)标准PHP类库,用于解决典型问题的一组接口与类的集合。
    class OrderListener implements \SplSubject {
        //观察者列表
        public $observers;
        public function __construct() {
            //SplObjectStorage类提供从对象到数据的映射,或者通过忽略数据,提供对象集的映射。在许多需要唯一标识对象的情况下,这种双重用途非常有用。
            $this->observers = new \SplObjectStorage();
        }
        //添加要通知的对象
        public function attach(\SplObserver $observer) {
            $this->observers->attach($observer);
        }
        //移除要通知的对象
        public function detach(\SplObserver $observer) {
            $this->observers->detach($observer);
        }
        //通知
        public function notify() {
            //将迭代器(此处可以理解为指针)倒回到第一个存储元素。
            $this->observers->rewind();
            //判断指针是否有效
            while($this->observers->valid()) {
                //获取当前的观察者
                $curr_obj = $this->observers->current();
                //对当前观察者进行通知
                $curr_obj->update($this);
                //向下移动指针
                $this->observers->next();
            }
        }
        //触发通知
        public function buyGoods() {
            echo '购买成功' . PHP_EOL;
            $this->notify();
        }
    }
    //SplObserver接口与SplSubject接口一起使用,以实现观察者设计模式。
    class Mail implements \SplObserver {
        //对被观察的对象做相应的处理
        public function update(\SplSubject $subject) {
            echo '发送邮件' . PHP_EOL;
        }
    }
    class Sms implements \SplObserver {
        //对被观察的对象做相应的处理
        public function update(\SplSubject $subject) {
            echo '发送短信' . PHP_EOL;
        }
    }
    $listener = new OrderListener();
    //添加观察者
    $listener->attach(new Mail());
    $listener->attach(new Sms());
    $listener->buyGoods();
    通知代码(基于SPL实现的notify方法优化)
            //以上代码的notify方法使用原生手动调整指针的方式去实现。也可以使用foreach去遍历实现
        public function notify() {
            foreach ($this->observers as $observer) {
                $observer->update($this);
            }
        }
    到此这篇关于PHP设计模式中观察者模式详解的文章就介绍到这了,更多相关PHP观察者模式内容请搜索知鸟论坛以前的文章或继续浏览下面的相关文章希望大家以后多多支持知鸟论坛!
  • 发表于 2023-6-29 02:32:45 | 显示全部楼层
    李志敏 2023-6-29 02:32:45 看全部
    我看不错噢 谢谢楼主!知鸟论坛越来越好!
    发表于 2023-6-29 14:08:02 | 显示全部楼层
    我的苦恼冉 2023-6-29 14:08:02 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    发表于 2023-6-29 14:10:17 | 显示全部楼层
    123456848 2023-6-29 14:10:17 看全部
    我看不错噢 谢谢楼主!知鸟论坛越来越好!
    发表于 2023-6-29 17:06:21 | 显示全部楼层
    Gordon520 2023-6-29 17:06:21 看全部
    楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
    发表于 2023-6-29 17:16:42 | 显示全部楼层
    123456868 2023-6-29 17:16:42 看全部
    其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
    发表于 2023-6-29 22:18:39 | 显示全部楼层
    素色流年783 2023-6-29 22:18:39 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    发表于 2023-6-30 02:16:42 | 显示全部楼层
    冀苍鸾 2023-6-30 02:16:42 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    发表于 2023-6-30 09:49:00 | 显示全部楼层
    术数古籍专卖疤 2023-6-30 09:49:00 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛。
    发表于 2023-7-3 14:19:51 | 显示全部楼层
    永远爱你冰塘 2023-7-3 14:19:51 看全部
    楼主,大恩不言谢了!知鸟论坛是最棒的!
    • 您可能感兴趣
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| 小黑屋| 知鸟论坛 |网站地图
    本站资源来自互联网用户收集发布,如有侵权请邮件联系处理。 联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表