设计模式-观察者模式
观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作。
观察者模式定义对象的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
设计原则
在观察者模式中,会改变的是主题的状态以及观察者的数目,用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题 -- 找出程序中会变化的方面,然后将其和固定不变的方面相分离。
主题和观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点 ——针对接口编程,而不针对实现编程。
观察者模式利用“组合”将许多观察者组合进主题中。对象(观察者——主题)之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生的。 ——多用组合,少用继承。
从面相对象的角度来看,主题提供注册和通知的接口,观察者提供自身操作的接口。(这些观察者拥有一个同一个接口)观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。观察者模式更多体现了两个独立的类,利用接口完成一件原本很复杂的事情。不利用主题类的话,我们就需要不断循环创建实例,执行操作。而现在只需要创建实例即可,执行操作只需要调用一次通知的方法即可。
/** * 观察者模式 */ class Paper{ /*主题*/ private $_observers = array(); public function register($sub){ /*注册观察者*/ $this->_observers[] = $sub; } public function trigger(){ /*外部统一访问*/ if(!empty($this->_observers)){ foreach($this->_observers as $observer){ $observer->update(); } } } } /** * 观察者要实现的接口 */ interface Observerable{ public function update(); } class Subscriber implements Observerable{ public function update(){ echo "Callback\n"; } }
下面是测试代码:
/*测试*/ $paper = new Paper(); $paper->register(new Subscriber()); //$paper->register(new Subscriber1()); //$paper->register(new Subscriber2()); $paper->trigger();
当新对象要填入的时候,只需要在主题(又叫可观察者)中进行注册(注册方式很多,你也可以在构造的时候,或者框架访问的接口中进行注册),然后实现代码直接在新对象的接口中进行。这降低了主题对象和观察者对象的耦合度。
场景:在一个事件发生后,要执行一连串更新操作,传统的编程方式就是在事件的代码后面直接加入处理逻辑,当更新的逻辑增多后,代码就会变得难以维护。这种方式是耦合的、侵入式的,增加新的逻辑需要改变事件主题的代码。而观察者模式实现了低耦合、非侵入式的通知与更新机制。