PHP 设计模式(三):观察者模式

什么是观察者模式

观察者模式,属于行为型模式。观察者模式有时也被称作发布/订阅模式,该模式用于为对象实现发布/订阅功能:一旦主体对象状态发生改变,与之关联的观察者对象会收到通知,并进行相应操作。

将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。 消息队列系统、事件都使用了观察者模式。

PHP 为观察者模式定义了两个接口:SplSubject 和 SplObserver。
SplSubject 可以看做主体对象的抽象,SplObserver 可以看做观察者对象的抽象,要实现观察者模式,只需让主体对象实现 SplSubject ,观察者对象实现 SplObserver,并实现相应方法即可。

应用场景

跟发布/订阅类似,某些场景的改变需要通知其相关的模块做出相应改变,比如订单下单成功需要通知库存模块减库存、通知信息通知模块发送验证码、日志的记录等。

PHP 代码实现
<?php

/**
 * 观察者模式 : 被观察对象 (主体对象)
 * 主体对象维护观察者列表并发送通知
 * Class User
 */
class User implements SplSubject
{
    /**
     * 参数数据
     * user data
     * @var array
     */
    protected $data = array();

    /**
     * 观察者对象
     * observers
     * @var SplObjectStorage
     */
    protected $observers;

    public function __construct()
    {
        $this->observers = new SplObjectStorage();
    }

    /**
     * 注册观察者
     * @param SplObserver $observer
     * @return void
     */
    public function attach(SplObserver $observer)
    {
        $this->observers->attach($observer);
    }

    /**
     * 移除观察者
     * @param SplObserver $observer
     * @return void
     */
    public function detach(SplObserver $observer)
    {
        $this->observers->detach($observer);
    }

    /**
     * 通知观察者方法
     *
     * @return void
     */
    public function notify()
    {
        /**
         * @var SplObserver $observer
         */
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }

    /**
     * 设置参数
     * @param $name string 参数索引
     * @param $value string 参数值
     * @return void
     */
    public function __set($name, $value)
    {
        $this->data[$name] = $value;

        // 通知观察者用户被改变
        $this->notify();
    }
}

/**
 * 观察者对象
 * Class UserObserver
 */
class UserObserver implements \SplObserver
{
    /**
     * 观察者要实现的唯一方法
     * 也是被 Subject 调用的方法
     * @param SplSubject $subject
     */
    public function update(SplSubject $subject)
    {
        echo get_class($subject) . ' has been updated';
    }
}

//=======================观察者调用===============================

//测试通知
$subject = new User();
$observer = new UserObserver();
$subject->attach($observer);
//触发__set
$subject->id = '1126';

echo '<hr>';//横线

//测试订阅
$subject = new User();

$subject->attach($observer);
$subject->detach($observer);

echo '已订阅';

echo '<hr>';//横线

//测试 update() 调用
$subject = new User();
$subject->attach($observer);

$subject->notify();

//结果
//User has been updated
//已订阅
//User has been updated

参考资料:
https://xueyuanjun.com/post/2935

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值