php设计模式-观察者

观察者模式的利弊之处,观察者模式 常用啊,比如说一个商城,进行购物完以后,要进行多方通知,

或者有各种相关业务需要处理,

传统方式是 顺序执行,直接在内部处理。

这样的话 存在的问题是,

一 . 一旦某个业务逻辑 发送改变,整个代码都得改变,给测试也增加困难,

二. 日记月累之下,文件冗长,后续维护困难。

存在的问题 主要是程序的紧密耦合,使用观察者模式 将业务逻辑优化成松耦合,达到易维护易修改的目的,同时也符合面向接口编程的思想

观察者典型实现方式

定义2个接口

观察者(通知) 被观察者(主题)

定义2个类

观察者类实现观察者接口 ,主题类实现被观察者接口

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

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


  • 观察者模式的效果有以下的优点:第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。观察者模式有下面的缺点:第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

  • 观察者模式的效果有以下的优点:

    第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

    由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

    第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

    观察者模式有下面的缺点:

    第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

    第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

    第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

  • 观察者模式的应用场景: 
    1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。 
    2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

下面放一个实例 代码


interface ITicketObserver{ //观察者接口
   function notify($sender,$arg);
}

interface ITicketObservable{//主题类接口
   function addObserver($obj);//提供注册观察者方法
}


class Hi implements ITicketObservable {
   private $obersvers;

   function addObserver( $obj)
   {

       $this->obersvers[] = $obj;
   }

   function buyTicket($ticket){
       foreach ($this->obersvers as $v){
           $v->notify($this,$ticket);//$this可用来获取主题类句柄,在通知中使用
       }
   }

}


//短信日志通知
class MSM implements ITicketObserver {
   public function notify($sender, $ticket) {
       echo (date ( 'Y-m-d H:i:s' ) . " 短信日志记录:购票成功:$ticket<br>");
   }
}
//文本日志通知
class Txt implements ITicketObserver {
   public function notify($sender, $ticket) {
       echo (date ( 'Y-m-d H:i:s' ) . " 文本日志记录:购票成功:$ticket<br>");
   }
}
//抵扣卷赠送通知
class DiKou implements ITicketObserver {
   public function notify($sender, $ticket) {
       echo (date ( 'Y-m-d H:i:s' ) . " 赠送抵扣卷:购票成功:$ticket 赠送10元抵扣卷1张。<br>");
   }
}


$buy = new Hi ();
$buy->addObserver ( new MSM () ); //根据不同业务逻辑加入各种通知
$buy->addObserver ( new Txt () );
$buy->addObserver ( new DiKou () );
//购票
$buy->buyTicket ( "一排一号" );


nickname
content