PHP设计模式-观察者模式

| 分类:PHP设计模式 | 评论: 0 | 浏览:6737

说明

观察者模式也称为发布订阅模式
定义:Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)

理解

可能从上面的定义中很难深入去理解观察者模式的含义。
假如我们现在需要一个订单系统,定义如下:

<?php
class Order {
        private $orderId;
        
        private $total;
        
        public function create(){
                echo "创建订单";
        }
        
        public function update(){
                echo "更新订单";
        }
        
        public function paid(){
                echo "订单已支付";
        }
        
        public function delete(){
                echo "订单已删除";
        }
}

上面我们定义了一个订单类
现在我们开始订单的创建流程:创建->修改->支付->删除

$order = new Order();
$order->create();
$order->update();
$order->paid();
$order->delete();

好了,上面已经完成了一个订单的大概流程,如果现在新增了一个需求:在订单的创建、支付两个步骤完成时发送信息通知用户。

开始定义发送信息类:

class SendMessage{
        private $userId;
        private $msg;
        
        public function send(){
                echo "信息发送成功";
        }
}

定义好了,给创建和支付步骤加上发送功能

class Order {
        private $orderId;
        
        private $total;
        
        public function create(){
                echo "创建订单";
                $message = new SendMessage();
                $message->send();
        }
        
        public function update(){
                echo "更新订单";
        }
        
        public function paid(){
                echo "订单已支付";
                $message = new SendMessage();
                $message->send();
        }
        
        public function delete(){
                echo "订单已删除";
        }
}

这样我们的需求就修改完成了。可是有一天,需求有改动,需要增加一个发送信息的同时发送邮件,这个时候我们还是继续往订单类里面去增加吗?
一方面这不符合类的设计原则,随着业务流程的完善,这个订单类会变得越来越冗余,难以维护。

这个时候我们就可以使用观察者模式,来监听订单的状态变化。

<?php

/**
 * 定义Order的接口
 * Interface OrderInterface
 */
interface OrderInterface{
    public function create();
    public function update();
    public function delete();
}

/**
 * 定义事件接口
 * Interface OrderEvent
 */
interface OrderEvent{
    public function notify();
}

/**
 * 实现发送信息的事件
 * Class SendMessage
 */
class SendMessage implements OrderEvent{
    /**
     * 事件的通知触发入口
     */
    public function notify ()
    {
        // TODO: Implement notify() method.
        echo "信息发送成功" . PHP_EOL;
    }
}

/**
 * 实现发送邮件的事件
 * Class SendEmail
 */
class SendEmail implements OrderEvent{
    /**
     * 事件的通知触发入口
     */
    public function notify ()
    {
        // TODO: Implement notify() method.
        echo "邮件发送成功" . PHP_EOL;
    }
}

/**
 * 实现订单类
 * Class Orders
 */
class Orders implements OrderInterface{
    /**
     * @var array 事件集
     */
    protected $even;

    /**
     * 监听事件
     * @param $action string 具体操作(create,update等)
     * @param OrderEvent $order_even 监听实类
     */
    public function listen($action,OrderEvent $order_even){
        $this->even[$action][] = $order_even;
    }


    public function create ()
    {
        // TODO: Implement create() method.
        echo "订单创建成功" . PHP_EOL;
        $this->hasChange('create');
    }
    public function delete ()
    {
        // TODO: Implement delete() method.
        echo "订单已被删除" . PHP_EOL;
        $this->hasChange('delete');
    }
    public function update ()
    {
        // TODO: Implement update() method.
        echo "订单修改成功" . PHP_EOL;
        $this->hasChange('update');
    }

    public function paid(){
        echo "订单已支付" . PHP_EOL;
        $this->hasChange('paid');
    }

    /**
     * 通知注册在事件集中的事件
     * @param $action string 操作
     */
    private function hasChange($action){
        echo "订单状态发生变化了" . PHP_EOL;
        if (isset($this->even[$action])){
            foreach ($this->even[$action] as $even){
                $even->notify();
            }
        }

    }
}

$sendEmail = new SendEmail();
$sendSMS = new SendMessage();

$order = new Orders();
// 为创建操作添加发送邮件事件
$order->listen('create',$sendEmail);
// 为创建操作添加发送信息事件
$order->listen('create',$sendSMS);
// 为删除操作添加发送邮件事件
$order->listen('delete',$sendEmail);
// 为支付操作添加发送邮件事件
$order->listen('paid',$sendEmail);
// 为支付操作添加发送信息事件
$order->listen('paid',$sendSMS);

$order->create();
$order->update();
$order->paid();
$order->delete();
Responses