观察者模式(Observer Pattern)

观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 何时使用:一个对象(目标对象)的状态发生改变,所有的依..


当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

应用实例:1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点:1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点:1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。

注意事项:1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

 

观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式是一种对象行为型模式。

模式动机
  建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。

观察者模式包含如下角色:
  Subject: 目标
  ConcreteSubject: 具体目标
  Observer: 观察者
  ConcreteObserver: 具体观察者

UML类图:

  ../_images/Obeserver.jpg

适用性:
  当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的

例如:红绿灯和等待通过得人,红绿灯就是被观察者,人和车就是观察者,由红灯变成绿灯,人和车都可以通过

 

//代码实现

复制代码
<?php
header("Content-type:text/html;Charset=utf-8");
//目标接口,定义观察目标要实现的方法
abstract class Subject{
   abstract function attach(Observer $observer);  //添加观察者
   abstract function detach(Observer $observer);  //去除观察者
   abstract function notify();  //满足条件时通知所有观察者修改
   abstract function condition($num); //发起通知的条件
}
//具体观察目标
class ConcreteSubject extends Subject{
    private $observers = array();
    //添加观察者
    function attach(Observer $observer){
         $this->observers[] = $observer;
    }
    //移除观察者
    function detach(Observer $observer){
         $key=array_search($observer, $this->observers);
         if($key !== false){  //注意不要写成!=,表达式0!=flase为flase
              unset($this->observers[$key]);
         }
    }
    //通知所有所有观察者修改
    function notify(){
        foreach($this->observers as $observer){
            $observer->update();
        }
    }
    //发起通知的条件
    function condition($num){
        if($num>100){
            $this->notify();
        }
    }
}

//抽象观察者接口,定义所有观察者共同具有的属性——执行修改
abstract class Observer{
    abstract function update();
}
//具体观察者类,实现抽象观察者接口
class ConcreteObserverA extends Observer{

    function update(){
       echo "A报告:敌军超过一百人了,快撤!<br>";
    }
    //其他函数
    function eat(){
        echo "A在吃饭";
    }
}
class ConcreteObserverB extends Observer{

    function update(){
       echo "B报告:敌军超过一百人了,快撤!<br>";
    }
    //其他函数
    function sleep(){
        echo "B在睡觉";
    }
}


//测试
$observerA = new ConcreteObserverA();
$observerB = new ConcreteObserverB();
$concreteSubject = new ConcreteSubject();
$concreteSubject->attach($observerA);  //添加观察者A
$concreteSubject->detach($observerA);  //去除观察者A
$concreteSubject->attach($observerA);
$concreteSubject->attach($observerB);
$concreteSubject->condition(1000);

 ?>
复制代码

 

posted @ 2020-03-02 16:32  笨笨韩  阅读(338)  评论(0)    收藏  举报