PHP模式设计----观察者模式(Observer)

一、模式定义:

观察者模式有时也称为发布/订阅模式,是一种一对多的依赖关系,一旦主体对象状态发生改变,与之关联的观察者对象就会收到通知,然后做相应处理。

二、适用场景及优缺点:

当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。
当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。
当一个
观察者模式的优点:
1.观察者和主题之间的耦合度较小;
2.支持广播通信;
观察者模式的缺点:
由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。

三、实现流程:
UML类图:
UML

主体提供接口:注册、通知、解除注册等。
观察者提供接口:相应的业务处理。
观察者利用主题注册函数进行注册,主体数据发生改变,通过通知接口调用观察者的业务处理接口。
PHP为观察者模式定义了两个接口:SplSubject和SplObserver。SplSbuject可以看做主体对象的抽象,
SplObserver可以看做观察者对象的抽象,要实现观察者模式,只需要让主体对象实现SplSubject,观察者对象实现SplObserver,
并实现相应方法即可。

三、实例分析:
主体代码:Test.php

<?php 
namespace App\Models;
use App\Models\TestObserver;
class Test implements \SplSubject{

        protected $data = array();
        public $property = 0;
    /**
     * observers
     *
     * @var \SplObjectStorage
     */
    protected $observers;

    public function __construct()
    {
        $this->observers = new \SplObjectStorage();
    }
    /**
     * 添加观察者
     *
     * @param \SplObserver $observer
     *
     * @return void
     */
    public function attach(\SplObserver $observer)
    {
        echo 'attach observer!';
        $this->observers->attach($observer);
    }
    /**
     * 取消观察者
     *
     * @param \SplObserver $observer
     *
     * @return void
     */
    public function detach(\SplObserver $observer)
    {
        $this->observers->detach($observer);
    }
    /**
     * 通知观察者方法
     *
     * @return void
     */
    public function notify()
    {
        echo 'notify observer!';
        /** @var \SplObserver $observer */
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
    /**
     *
     * @param string $name
     * @param mixed  $value
     *
     * @return void
     */
    public function __set($name, $value)
    {
        $this->data[$name] = $value;

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

然后是观察者代码:TestObserver.php

<?php 
namespace App\Models;
use App\Models\Test;

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

然后是个外部调用类:MyTest.php

<?php 
namespace App\Models;
use Log;
use App\Cache\BaseCache;
use App\Models\Test;
use App\Models\TestObserver;
class MyTest{
    protected $observer;
    /**
     * 测试通知
     */
    public function testNotify()
    {
        echo "测试通知";        
        $subject = new Test();
        $this->observer = new TestObserver();
        $subject->attach($this->observer);
        $subject->property = 123;
        $subject->notify();
    }
}

四、总结:主体和观察者的这种关系不是通过继承,而是通过组合,这样类之间的耦合性会低很多,同时一个主体也可以注册多个观察者。

以上内容参考自下面连接,为了便于理解在此记录。
原文参考:http://laravelacademy.org/post/2935.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值