详解PHP设计模式之观察者模式

巴扎黑
巴扎黑 原创
2023-03-15 10:36:02 977浏览


摘要:Yii2的事件采用了“观察者模式”,先了解观察者,再学事件就容易了。

它是什么

首先不要被名字所吓倒,往下看,它真的很简单。

先来一个比较高大上的定义:观察者模式定义了一系列对象之间的一对多关系,当一个对象改变状态后,其他依赖者都会收到通知。

看明白了么?

如果没明白我们再来一个生活一点的:观察者模式就是订报纸的模式,你和一些人向某个报社订报纸,只要有新报纸出版,报社就会给你们送来,具体你们怎么看和报社无关,只要报社不倒闭,就会一直给你们送。

当然,你也可以退订。

观察者模式 == 报社 + 订报纸的人

无论你明白了哪种定义,记住一点,“观察者模式”最牛逼的地方就是让一些彼此依赖的类松耦合,牛逼的系统是什么样的?那就是每个对象间的依赖程度降到冰点,但是依然可以交互。

Code it

我想到此刻,你已经清楚了观察者模式,但是作为一个语言类文章,不写点代码总说不过去,我们接下来用代码来实现上面的需求。

我们先来一个不用观察者模式的代码

class Video {    public function new(){
        $checkNewVideo = Video::find()->where("xxxxx")->one();        if($checkNewVideo){            //    通知各位
            LaoWang::newVideo();
            XiaoLi::newVideo();
            ChuanPu::newVideo();
            .......            //    还有很多很多,比如在给某个集体客户群发、短信发等等等等
        }
    }
}//    具体实现$model = new Video();
$model->new();

其实,在系统小的时候,这是非常快捷有效的方式。

但是,当系统变大的时候,这种方法马上面临难以扩展的问题,并且容易出错。

  • 比如老王不想订阅了,我们需要改源代码。

  • 比如又增加了一个客户,我们要去改源代码。

  • 比如xxx,我们都需要改源代码。

这两个对象的耦合度太高了。

解决它 - 用观察者模式

我们先改进上面的代码

/**
 * 被观察者接口
 * 定义了一些公用方法声明,使用观察者模式的类都可以继承此接口
 */interface Observable {    // 添加/注册观察者
    public function attach(Observer $observer);    // 删除观察者
    public function detach(Observer $observer);    // 触发通知
    public function notify();
}class Video implements Observable {    public $observers = [];//    订阅者

    //    添加观察者
    public function attach(Observer $observer){
        $key = array_search($observer, $this->observers);        if ($key === false) {            $this->observers[] = $observer;
        }
    }    //    删除观察者
    public function detach(Observer $observer){
        $key = array_search($observer, $this->observers);        if ($key !== false) {            unset($this->observers[$key]);
        }
    }    //    通知所有观察者
    public function notify(){        foreach ($this->observers as $observer) {            // 把本类对象传给观察者
            $observer->update($this);
        }
    }    public function  new(){
        $checkNewVideo = Video::find()->where("xxxxx")->one();        if($checkNewVideo){            $this->notify();
        }
    }
}

你看到了,修改后的代码并不关心具体发送给谁,它只是遍历了所有观察者的列表,然后告诉他们一下而已,观察者增减对此类不会有任何影响。

对于观察者,数字不定,随时有增减,因此我们定义了一个观察者接口开始抽象它们。

/**
 * 观察者接口
 */interface Observer{    // 接收到通知的处理方法
    public function update(Observable $observable);
}

老王、小明、川普、冰冰订阅了视频

class LaoWang implements Observer {    public function update(Observable $observable){        echo "立刻开始看视频";
    }
}class XiaoMing implements Observer {    public function update(Observable $observable){        echo "收到后忽略通知";
    }
}class ChuanPu implements Observer {    public function update(Observable $observable){        echo "收藏了一下,然后去wc看";
    }
}class BingBing implements Observer {    public function update(Observable $observable){        echo "立刻开始看视频";
    }
}

具体实现

$model = new Video();
$model->attach(new LaoWang());
$model->attach(new XiaoLi());
$model->attach(new ChuanPu());
$model->attach(new BingBing());
$model->new();

这样当我们再增加一个人加入 习大大 的时候,我们只需要增加一个习大大的观察者类,在实现的时候添加注册,而不需要去改Video类和其他的观察者类,将类之间的耦合降低了很多。

回头看

上面就是观察者模式,我们先预想一下我们的事件,假设我们定义了很多观察者代码,他们监听事件的发生,当一个事件被触发,这些观察者都会知道,执行各自的逻辑。

事件就是观察者模式的一种应用。

监听系统的某一个行为,实时获取并执行自己负责的代码。

以上就是详解PHP设计模式之观察者模式的详细内容,更多请关注php中文网其它相关文章!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。