PHP设计模式-观察者模式

1、概念:

  其实观察者模式这是一种较为容易去理解的一种模式吧,它是一种事件系统,意味 着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间

紧密耦合的另一种方法

  观察者模式(Observer),当一个对象的状态发生改变时,依赖他的对象会全部收到通知,并自动更新。

  场景:一个事件发生后,要执行一连串更新操作.传统的编程方式,就是在事件的代码之后直接加入处理逻辑,当更新得逻辑增多之后,代码会变得难以维护.这种方式是耦合的,侵入式的,增加新的逻辑需要改变事件主题的代码

观察者模式实现了低耦合,非侵入式的通知与更新机制

2、关键点:   

  1.被观察者->追加观察者;->一处观察者;->满足条件时通知观察者;->观察条件

  2.观察者 ->接受观察方法

3、优缺点:   

  优点:1.观察者和主题之间的耦合度较小;2.支持广播通信;

  缺点:由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新

4、观察者模式在PHP中的应用场合:在web开发中观察者应用的方面很多  

  典型的:用户注册(验证邮件,用户信息激活),购物网站下单时邮件/短信通知等

5、php内部的支持  

  SplSubject 接口,它代表着被观察的对象,

其结构:

php内部类,SplSubject
interface SplSubject {   public function attach(SplObserver $observer);   public function detach(SplObserver $observer);   public function notify(); }

SplObserver 接口,它代表着充当观察者的对象,

其结构:

php内部类,SplObserver
interface SplObserver
{ 
    public function update(SplSubject $subject);
}

使用PHP内部类例子:

class MyObserver1 implements SplObserver {
    public function update(SplSubject $subject) {
        echo __CLASS__ . ' - ' . $subject->getName();
    }
}

class MyObserver2 implements SplObserver {
    public function update(SplSubject $subject) {
        echo __CLASS__ . ' - ' . $subject->getName();
    }
}

class MySubject implements SplSubject {
    private $_observers;
    private $_name;

    public function __construct($name) {
        $this->_observers = new SplObjectStorage();
        $this->_name = $name;
    }

    public function attach(SplObserver $observer) {
        $this->_observers->attach($observer);
    }

    public function detach(SplObserver $observer) {
        $this->_observers->detach($observer);
    }

    public function notify() {
        foreach ($this->_observers as $observer) {
            $observer->update($this);
        }
    }

    public function getName() {
        return $this->_name;
    }
}

$observer1 = new MyObserver1();
$observer2 = new MyObserver2();

$subject = new MySubject("test");

$subject->attach($observer1);
$subject->attach($observer2);
$subject->notify();

自己自定义类例子:

#===================定义观察者、被观察者接口============
/**
 *
 * 观察者接口(通知接口)
 *
 */
interface ITicketObserver //观察者接口
{
  function onBuyTicketOver($sender, $args); //得到通知后调用的方法
}
/**
 *
 * 主题接口
 *
 */
interface ITicketObservable //被观察对象接口
{
  function addObserver($observer); //提供注册观察者方法
}
#====================主题类实现========================
/**
 *
 * 主题类(购票)
 *
 */
class HipiaoBuy implements ITicketObservable { //实现主题接口(被观察者)
  private $_observers = array (); //通知数组(观察者)
  public function buyTicket($ticket) //购票核心类,处理购票流程
{
    // TODO 购票逻辑
    //循环通知,调用其onBuyTicketOver实现不同业务逻辑
    foreach ( $this->_observers as $obs )
      $obs->onBuyTicketOver ( $this, $ticket ); //$this 可用来获取主题类句柄,在通知中使用
  }
  //添加通知
  public function addObserver($observer) //添加N个通知
{
    $this->_observers [] = $observer;
  }
}
#=========================定义多个通知====================
//短信日志通知
class HipiaoMSM implements ITicketObserver {
  public function onBuyTicketOver($sender, $ticket) {
    echo (date ( 'Y-m-d H:i:s' ) . " 短信日志记录:购票成功:$ticket<br>");
  }
}
//文本日志通知
class HipiaoTxt implements ITicketObserver {
  public function onBuyTicketOver($sender, $ticket) {
    echo (date ( 'Y-m-d H:i:s' ) . " 文本日志记录:购票成功:$ticket<br>");
  }
}
//抵扣卷赠送通知
class HipiaoDiKou implements ITicketObserver {
  public function onBuyTicketOver($sender, $ticket) {
    echo (date ( 'Y-m-d H:i:s' ) . " 赠送抵扣卷:购票成功:$ticket 赠送10元抵扣卷1张。<br>");
  }
}
#============================用户购票====================
$buy = new HipiaoBuy ();
$buy->addObserver ( new HipiaoMSM () ); //根据不同业务逻辑加入各种通知
$buy->addObserver ( new HipiaoTxt () );
$buy->addObserver ( new HipiaoDiKou () );
//购票
$buy->buyTicket ( "一排一号" );

注意:

观察者模式典型实现方式:

1、定义2个接口:观察者(通知)接口、被观察者(主题)接口,可直接使用PHP内部类

2、定义2个类,观察者对象实现观察者接口、主题类实现被观者接口

3、主题类注册自己需要通知的观察者

4、主题类某个业务逻辑发生时通知观察者对象,每个观察者执行自己的业务逻辑。