php 设计模式之观察者模式
实例
没用设计模式的代码,这样的代码要是把最上面那部分也要符合要求加进来,就要修改代码,不符合宁增不改的原则
介绍
观察者模式定义对象的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新!
所有的观察者(observer)全部被注册(register函数)进入数组(事件的_observers[]数组),这样,当事件(例子中是paper)有变化的时候,就能通过遍历(代码19行)来通知所有的观察者。每个观察者再做他们自己对应的更新(代码20行)。
设计原则
在观察者模式中,会改变的是主题的状态以及观察者的数目。用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题。——找出程序中会变化的方面,然后将其和固定不变的方面相分离!
主题和观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点! ——针对接口编程,不针对实现编程!
。
观察者模式利用“组合”将许多观察者组合进主题中。对象(观察者——主题)之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生的。 ——多用组合,少用继承!
代码
1 <?php 2 /** 3 * 观察者模式 4 * @author: Mac 5 * @date: 2012/02/22 6 */ 7 8 9 class Paper{ /* 主题 */ 10 private $_observers = array(); 11 12 public function register($sub){ /* 注册观察者 */ 13 $this->_observers[] = $sub; 14 } 15 16 17 public function trigger(){ /* 外部统一访问 */ 18 if(!empty($this->_observers)){ 19 foreach($this->_observers as $observer){ 20 $observer->update(); 21 } 22 } 23 } 24 } 25 26 /** 27 * 观察者要实现的接口 28 */ 29 interface Observerable{ 30 public function update(); 31 } 32 33 class Subscriber implements Observerable{ 34 public function update(){ 35 echo "Callback "; 36 } 37 }
下面是测试代码
1 /* 测试 */ 2 $paper = new Paper(); 3 $paper->register(new Subscriber()); 4 //$paper->register(new Subscriber1()); 5 //$paper->register(new Subscriber2()); 6 $paper->trigger();
总结
当新对象要填入的时候,只需要在主题(又叫可观察者)中进行注册(注册方式很多,你也可以在构造的时候,或者框架访问的接口中进行注册),然后实现代码直接在新对象的接口中进行。这降低了主题对象和观察者对象的耦合度。
好的设计模式不会直接进入你的代码中,而是进入你的大脑中。
另一份代码
1 /** 2 * 事件产生类 3 * Class EventGenerator 4 */ 5 abstract class EventGenerator 6 { 7 private $ObServers = []; 8 9 //增加观察者 10 public function add(ObServer $ObServer) 11 { 12 $this->ObServers[] = $ObServer; 13 } 14 15 //事件通知 16 public function notify() 17 { 18 foreach ($this->ObServers as $ObServer) { 19 $ObServer->update(); 20 } 21 } 22 23 } 24 25 /** 26 * 观察者接口类 27 * Interface ObServer 28 */ 29 interface ObServer 30 { 31 public function update($event_info = null); 32 } 33 34 /** 35 * 观察者1 36 */ 37 class ObServer1 implements ObServer 38 { 39 public function update($event_info = null) 40 { 41 echo "观察者1 收到执行通知 执行完毕! "; 42 } 43 } 44 45 /** 46 * 观察者1 47 */ 48 class ObServer2 implements ObServer 49 { 50 public function update($event_info = null) 51 { 52 echo "观察者2 收到执行通知 执行完毕! "; 53 } 54 } 55 56 /** 57 * 事件 58 * Class Event 59 */ 60 class Event extends EventGenerator 61 { 62 /** 63 * 触发事件 64 */ 65 public function trigger() 66 { 67 //通知观察者 68 $this->notify(); 69 } 70 } 71 72 //创建一个事件 73 $event = new Event(); 74 //为事件增加旁观者 75 $event->add(new ObServer1()); 76 $event->add(new ObServer2()); 77 //执行事件 通知旁观者 78 $event->trigger();