/ dp

DP 观察者模式

还记得上一章提到小俞写的三个项目吗,一个博客,一个cms内容管理,一个商城。小俞有段时间实在太忙了,已经没有精力去同时管理自己的三个项目,于是乎他把商城项目交付给了小易帮忙管理。

一段时间内商城的运作一切正常,突然有一天,小易的邮箱收到好几封用户的投诉邮件,邮件的内容大致相同。大多都是在说下单后出了问题了,以前下单会收到订单的短信和微信的通知,但是现在收不到了,下单后本来还有一个红包可以领取,现在也没了,用户都不知道自己有没有下单成功了。

小易赶忙打开代码找到了下单的操作,看到了之前小俞的代码。

class Order
{
    public function buy($code) {
        // 购买的数据流程
        echo "下单中...";
        $this->code = $code;
        
        // 下单后的操作
        // 1.记录订单日志
        echo "记录日志,订单号{$this->code}";
        // 2.发送短信通知
        echo "短信消息:您的订单号{$this->code}";
        // 3.发送微信通知
        echo "微信消息:您的订单号{$this->code}";
        // 4.生成红包
        echo "订单号{$this->code}生成了一个红包";
    }
}

可以看到下单后有4个操作,生成日志记录,发送短信通知,发送微信通知,生成红包。小易开始在对每个操作逐步测试,首先查看了订单的生成日志,发现日志是生成了,然后测试短信发送,终于发现了问题。小易仔细调试后发现是短信服务的发送余额不足了,大概是余额不足的通知还是发送给小俞的自己没看到。小易大喊一声坑爹后,发了微信叫小俞赶紧去续费。

结束这一切后的小易松了一口气,点了一根烟细想了这个事件,发现这样做可不行啊。你看现在就是因为短信这一个业务出了问题结果导致后面的所有操作没有执行,而且以后万一出现问题,调试起来是很费力,因为所有下单后的业务都挤在一块,也不方便以后的扩展。于是乎,小易决定用观察者模式重写下这块业务,以此好好教育下小俞的粗心。

观察者也是一个类,这个类是专门用来观察目标类对象的变化,来做出相应的处理。

interface Observer {
    public function onAfterBuy($order);
}

class WxMessageObserver implements Observer
{
    public function onAfterBuy($order)
    {
	// 微信推送购买消息
        echo "微信消息:您的订单号{$order->code}";
    }
}

class SmsMessageObserver implements Observer
{
    public function onAfterBuy($order)
    {
        // 发送购买通知短信
        echo "短信消息:您的订单号{$order->code}";
    }
}

class RedPacketObserver implements Observer
{
    public function onAfterBuy($order)
    {
        // 生成红包
        echo "订单号{$order->code}生成了一个红包";
    }
}

class Order
{
    public $code = '';
    public $observer = [];

    public function buy($code)
    {
        // 购买的数据流程...
        $this->code = $code;

        foreach ($this->observer as $observer) {
            $observer->onAfterBuy($this);
        }
    }

    public function register($observer) {
        $this->observer[] = $observer;
    }
}

$order = new Order();
$order->register(new WxMessageObserver());
$order->register(new SmsMessageObserver());
$order->register(new RedPacketObserver());
$order->buy('123456');

在这里,我们创建了一个观察者接口,以及3个观察者类,3个观察类的onAfterBuy方法就是处理下单后的操作。WxMessageObserver类用来处理订单下单的微信推送,SmsMessageObserver类用来处理下单后的短信发送,RedPacketObserver类用来处理下单后的红包生成。

然后在我们Order类中添加一个register方法用来注册观察者来建立与观察者类的联系,并且在buy方法中去触发观察者的行为onAfterBuy

通过观察者模式,我们将下单这一行为的后续操作分离成观察者的行为,目标类不需要关心具体发生了什么,只要去执行观察者提供的方法就可以了。

完。下一章