首页 PHP 正文
270

设计模式之观察者模式

观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)。从名称上可以大概知道,观察者模式包括两个主体:被观察对象与观察对象。一般来说,被观察对象与观察对象是一对多的关系,被观察者发生状态改变时,要通知给它的所有观察者,观察者感知到变化之后再做出相应的反应。
/**
*观察者接口
*/
interface Observer{
    /**
    *观察者角色需要实现一个update方法,用于处理被观察者发来的通知。
    */
    public function update(Subject $subject);
}

/**
*具体观察者1
*/
class ConcreteObserver1 implements Observer{
    private $status;
    
    /**
    *实现接口的update方法
    */
    public function update(Subject $subject){
        $this->status = $subject->getStatus();
    }
    
    public function getStatus(){
        return $this->status;
    }
}

/**
*具体观察者2
*/
class ConcreteObserver2 implements Observer{
    private $status;
    /**
    *实现接口的update方法
    */
    public function update(Subject $subject){
        $this->status = $subject->getStatus();
    }
    
    public function getStatus(){
        return $this->status;
    }
}

/**
*被观察者接口
*/
interface Subject{ 
    public function addObserver(Observer $observer);//增加订阅
    public function removeObserver(Observer $observer);//解除订阅
    public function notify();//给所有订阅对象发送通知
}

/**
*被观察者类
*/
class ConcreteSubject implements Subject{
    private $observers = array();
    private $status;
    
    public function addObserver(Observer $observer){
        if(!in_array($observer, $this->observers, true)){
            $this->observers[] = $observer;
        }
    }
    
    public function removeObserver(Observer $observer){
        if(false!==($index = array_search($observer, $this->observers, true))){
            unset($this->observers[$index]);
        }
    }
    
    public function setStatus($status){
        $this->status = $status;
    }
    
    public function getStatus(){
        return $this->status;
    }
    
    public function notify(){
        foreach($this->observers as $observer){
            $observer->update($this);
        }
    }
}

$subject = new ConcreteSubject();
$subject->setStatus('status is ok!');

$observer1 = new ConcreteObserver1();
$subject->addObserver($observer1);

$observer2 = new ConcreteObserver2();
$subject->addObserver($observer2);

$subject->notify();

echo 'Observer1:'.$observer1->getStatus().'<br>';
echo 'Observer2:'.$observer2->getStatus().'<br>';
观察者模式的应用场景:
1、  对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、  对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
观察者模式的优点:
1、  Subject和Observer之间是松偶合的,分别可以各自独立改变。
2、  Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
3、  遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
观察者模式的缺陷:
1、  松偶合导致代码关系不明显,有时可能难以理解。
2、  如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)

正在加载评论...