zoukankan      html  css  js  c++  java
  • php 设计模式之观察者模式(订阅者模式)

    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();
  • 相关阅读:
    csuoj 1355: 地雷清除计划
    Task 6.4 冲刺Two之站立会议3
    Task 10 统计从1到某个整数之间出现的1的次数
    Task 6.3 冲刺Two之站立会议2
    Task 9 从用户界面和体验分析“360极速浏览器”
    Task 6.3 冲刺Two之站立会议1
    《程序员开发心理学》阅读笔记一
    Task 6.2冲刺会议十 /2015-5-23
    Task 6.2冲刺会议九 /2015-5-22
    Task 6.2冲刺会议八 /2015-5-21
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/8651812.html
Copyright © 2011-2022 走看看