PHP设计模式之观察者模式

观察者模式(Observer Design Pattern) 也被称为 发布订阅模式(Publish-SubscribeDesign Pattern),在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者 (Observer)。

观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子,比如,邮件订阅、RSS Feeds,本质上都是观察者模式。不同的应用场景和需求下,这个模式也有截然不同的实现方式,有同步阻塞的实现方式,也有异步非阻塞的实现方式;有进程内的实现方式,也有跨进程的实现方式。

PHP中提供了 观察者(observer) 和 被观察者(subject) 的接口 SplSubject (PHP >= 5.1.0),https://www.php.net/manual/en/class.splsubject.php

SplSubject  {
     abstract public void attach ( SplObserver $observer )
     abstract public void detach ( SplObserver $observer )
     abstract public void notify ( void )
}

这里用PHP实现一个简单的观察者模式,设定场景为登录操作,如果登录尝试次数小于3次认为登录成功,否则登录失败。同时可以设定登录之后给指定的接口URL推送数据。代码如下:

<?php

/**
 * 根据 登录次数 和 推送URL 进行观察,
 * 定义user类,实现SplSubject接口
 */
class User implements SplSubject {
    public $login_count; //登录次数
    public $push_url; //推送的URL
    protected $observers; //储存被观察的对象

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

    /**
     * 登录操作
     */
    public function login() {
        //todo 登录的具体逻辑实现...

        //登录后,触发通知
        $this->notify();
    }

    /**
     * 观察
     */
    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()) {
            $observer = $this->observers->current();
            $observer->update($this);
            $this->observers->next();
        }
    }
}


/**
 * 假设现在有个 "安全模块" 要来观察, 设定登录次数小于3属于正常操作,否则属于异常操作
 */
class Security implements SPLObserver {
    public function update(SplSubject $subject) {
        if ($subject->login_count < 3) {
            echo '当前第' . $subject->login_count . '次登录,正常操作.';
        } else {
            echo '当前第' . $subject->login_count . '次登录,出现异常!';
        }
        echo PHP_EOL;
    }
}

/**
 * 假设现在又有个 "推送模块" 要来观察,登录成功后给xxx接口推送一条记录
 */
class Push implements SPLObserver {
    public function update(SplSubject $subject) {
        echo "给 {$subject->push_url} 推送登录数据";
        echo PHP_EOL;
    }
}

//实施观察, 实例化User
$user = new User(1, 'www.xxx.com');
//安全模块 的观察
$user->attach(new Security());
//推送模块 的观察
$user->attach(new Push());
//执行登录操作
$user->login();

/*
当前第1次登录,正常操作.
给 www.xxx.com 推送登录数据
*/

上面实例化User类的时候传递了“登录次数”值为1,因此返回 “当前第1次登录,正常操作.”,如果改成3,则会返回 “当前第3次登录,出现异常!”。

按照上面代码的设定,我们可以灵活的增加更多的观察者,比如登录成功后给用户增加积分、更新登录时间 等等。

源代码:https://gitee.com/rxbook/php_design_pattern/blob/master/code06_Observer.php

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮尘笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值