Loading

PHP设计模式:观察者模式

示例代码详见https://github.com/52fhy/design_patterns

观察者模式#

观察者模式(Observer)是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

观察者模式UML图:

观察者模式需要有4个角色:

  • Observer观察者抽象接口,只有一个待实现方法update()
  • 具体观察者(ConcreteObserver)角色:实现了抽象接口,实际应用里可能是日志观察者、短信推送观察者等等;
  • 主题(Subject)抽象类,用于添加观察者、触发观察者;
  • 具体主题的实现类(ConcreteSubject),通过change触发nodifyObservers方法。实际change和nodifyObservers可以合成一个。

下面以订单为例:当状态变化,需要进行相关处理,例如写日志、短信通知。

Observer观察者抽象接口:

namespace Yjc\Observer;

interface IObserver
{
    public function update($data);
}

具体的观察者:

namespace Yjc\Observer;

class LogObserver implements IObserver
{

    public function update($data)
    {
        echo 'write log to file.';
    }
}

class SmsObserver implements IObserver
{
    public function update($data)
    {
        echo 'send sms';
    }
}

抽象主题类:

namespace Yjc\Observer;

abstract class ISubject
{
    private  $observers = [];//观察者集合

    public function attach(IObserver $observer){
        array_push($this->observers, $observer);
    }

    public function detach(IObserver $observer){
        return false;
    }

    public function nodifyObservers($data){
        if(count($this->observers) == 0) return false;
        foreach ($this->observers as $observer){
            $observer->update($data);
        }
    }

    public abstract function change($data);

}

实现了抽象主题的订单主题:

namespace Yjc\Observer;

class OrderSubject extends ISubject
{
    public function change($data)
    {
        $this->nodifyObservers($data);
    }
}

测试:

$order_subject = new OrderSubject();
$order_subject->attach(new LogObserver());//写日志
$order_subject->attach(new SmsObserver());//发短信
$order_subject->change(['oid' => '1', 'flag' => 3]);//订单状态变化,触发观察者

输出:

write log to file.
send sms

观察者实际还区分推模型和拉模型。上述讲的是推模型。推模型主动将观察者需要的数据$data通过update()传递过去;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。具体查看:《JAVA与模式》之观察者模式

posted @   飞鸿影  阅读(894)  评论(0编辑  收藏  举报
编辑推荐:
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
阅读排行:
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 千万级的大表,如何做性能调优?
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· .NET周刊【1月第1期 2025-01-05】
历史上的今天:
2016-06-25 CentOS 7 网络配置
2016-06-25 常用正则表达式收藏
点击右上角即可分享
微信分享提示
主题色彩