PHP中的观察者模式介绍

观察者模式

描述:

这个观察者模式,大家可以去翻阅一下PHP手册中的这两个接口,下面我的代码是根据这两个接口来实现的

在公司上,我也有遇到过需要观察者模式的,就好比如,众多商品小表修改完之后,要统计在商品大表,这时候就可以考虑观察者模式了

PHP中的接口如下:SplSubject,SPLObserver

第一个使用场景

当报纸发布消息, 每一个用户都会得到通知。这就是观察者模式的使用场景。

第二个应用场景

比如按業務來說的話,常見的就好比註冊、下訂單:

  • 註冊:一般會跟活動掛鉤,比如註冊送金幣、積分之類的;包括推薦人之類
  • 下訂單就比較多了,活動是最起碼的;其次比如發短信、郵件等

以上是常見的場景。其實按到現實生活中的例子就是:警察來了,就得通知各個商販趕緊跑路。其中警察就是被觀察者,那些商販就是觀察者。

第三个使用场景

 场景描述:

 哈票以购票为核心业务(此模式不限于该业务),但围绕购票会产生不同的其他逻辑,如:

1、购票后记录文本日志

2、购票后记录数据库日志

3、购票后发送短信

4、购票送抵扣卷、兑换卷、积分

5、其他各类活动等

传统解决方案:在购票逻辑等类内部增加相关代码,完成各种逻辑。

存在问题:

1、一旦某个业务逻辑发生改变,如购票业务中增加其他业务逻辑,需要修改购票核心文件、甚至购票流程。

2、日积月累后,文件冗长,导致后续维护困难。

存在问题原因主要是程序的"紧密耦合",使用观察模式将目前的业务逻辑优化成"松耦合",达到易维护、易修改的目的,

同时也符合面向接口编程的思想。

<?php
// php 实现观察者
// php5中提供观察者observer与被观察者subject的接口

// user ab 是被观察
// SplSubject 实现这个接口就要实现三个方法
class user implements SplSubject
{
     public $lognum;
    public $hobby;
    protected $observers = null;

    public function __construct($hobby)
    {
        $this->lognum = rand(1, 10);
        $this->hobby = $hobby;
        $this->observers = new SplObjectStorage();
    }

    /***
     * 登录
     */
    public function login()
    {
        // 操作session
        $this->notify();// 调用了,将观察的东西都给我通知!
    }

    // 1 第一个方法 附加,附加一个SplObserver,以便可以将其通知更新。
    public function attach(SPLObserver $observer)
    {
        $this->observers->attach($observer);
    }

    // 2 第二个方法 分离,将观察者从主题上移开,不再通知其更新。
    public function detach(SPLObserver $observer)
    {
        $this->observers->detach($observer);
    }

    // 3 第三个方法 通知,通知所有附加的观察者。
    public function notify()
    {
        $this->observers->rewind();
        // rewind 里面存储了很多要通知的对象, 将迭代器后退到第一个存储元素
        // valid 不断判断里面的对象
        // current 获取里面的对象
        // update 接收主题更新
        // next 下一个
        while ($this->observers->valid()) {
            $observer = $this->observers->current();
            $observer->update($this);
            $this->observers->next();
        }
    }
}

// 登录安全的
class secrity implements SPLObserver
{
    public function update(SplSubject $subject)
    {
        // TODO: Implement update() method.
        if ($subject->lognum < 3) {
            echo "这是第" . $subject->lognum . '次安全登录';
        } else {
            echo "这是第" . $subject->lognum . '次安全,异常';
        }
    }
}

// 对应的人返回对应的需求
class ad implements SPLObserver
{
    public function update(SplSubject $subject)
    {
        // TODO: Implement update() method.
        if ($subject->hobby == 'sports') {
            echo '台球英锦赛门票预订';
        } else {
            echo '好好学习,天天向上';
        }
    }
}

// 实施观察
$user = new user('study');
$user->attach(new secrity());// 观察它
$user->attach(new ad()); // 观察它
$user->login();
发布了6 篇原创文章 · 获赞 7 · 访问量 110

猜你喜欢

转载自blog.csdn.net/qq_41672878/article/details/104859865
今日推荐