设计模式之观察者--发布订阅实现原理

设计模式之观察者–发布订阅实现原理

观察者模式是一种发布订阅模式,一对多的推送关系,当观察者监听的对象发生改变时,通知所有的观察者对象。

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

为什么要使用观察者模式

观察者模式解耦了观察者被观察者。当你有一处改变需要通知多个地方的时候就可以用观察者模式。

比如vue这种前端组件,里面就使用了观察者模式进行双向数据流的绑定,当你的数据更改的时候会通知这个数据的观察者更改显示,或者当显示更改的时候通知观察者更改数据。

比如laravel框架中内置了observer观察者,用来观察数据库的改动。假设你有一个用户支付成功后发放积分的需求,那么你可以观察订单的状态,如果状态成功那么通过observer来发放积分。这样也实现了解耦核心业务非核心业务

一个最简单的观察者实现如下所示


/**
 * 观察者模式
 * 观察者接口
 */
interface observer{
    function update();
}

class observer1 implements observer{
    function update() {
        //订单成功后发放积分
    }
}

class observer2 implements observer{
    function update() {
        //订单成功后发放优惠券
    }
}

/**
 * 观察者模式
 * 通知者负责通知所有具体观察者
 * 通知者需要存储要通知哪些具体观察者
 */
class subject{
    private $observers = [];

    function add(observer $observer) {
        $this->observers[] = $observer;
    }

    function notify() {
        foreach ($observers as $observer) {
            $observer->update();
        }
    }
}

$subject = new subject;
//注册观察者
$subject->add(new observer1);
$subject->add(new observer2);
//通知观察者
$subject->notify();

上面的实现核心其实就在于把所有的观察者注册到一个数组中,然后出现变动的时候遍历数组通知每一个观察者。

当一个对象的改变需要同时改变其他对象,并且还不知道具体有多少对象要改变。这种情况下使用观察者模式可以解耦这一个对象和其他需要改变的对象。

比如订单状态的改变需要同时改变用户的积分等。

subject通知类可以写成一个单独的通知类,也可以直接就是业务类,如果嫌麻烦并且逻辑简单啥的可以直接把观察者注册到业务类中,但是最好还是单独写出来。

除了这种一对多的关系还有一对一的生产者-消费者关系。我觉得生产者和消费者也算是观察者,只不过只有一个具体观察者的观察者模式。

很多消息队列都支持一对一的生产-消费关系,还有部分消息队列也支持发布订阅这种一对多的消费模式。

代码放在了我的github上面。

原创文章 84 获赞 7 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Thepatterraining/article/details/105976147