设计模式之 观察者模式

      观察者模式是一种非常简单的事件系统,包含了两个或更多的互相交互的类。这一模式允许某个类观察另个类的状态。当被观察者的状态发生改变时就会通知所有观察者进行相应的变化。

* 观察者模式定义了一个一对多的依赖关系
* 让一个或多个观察者对象监察一个主题对象
* 这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象
* 使这些观察者对象能够自动更新。

 

实例一:

/*
* 当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。

  那么如何让各家电脑知道自己的盟友被攻击了呢?并且自动做出反应?

  待解决的问题:一旦某个电脑被我们进攻,其他电脑就获知,并且自动出兵救援。

  思路:为电脑设置一些额外的观察系统,由他们去通知其他电脑。

  观察者(Observer)模式示例:
*/



//抽象的结盟类
abstract class abstractAlly {

public $oberserverCollection; //放置观察者的集合,这里以简单的数组来直观演示
public function addOberserver($oberserverName){ //增加观察者的方法,参数为观察者(也是玩家)的名称
$this->oberserverCollection[] = new oberserver($oberserverName);//以元素的方式将观察者对象放入观察者的集合
}

public function notify($beAttackedPlayerName){ //将被攻击的电脑的名字通知各个观察者
foreach ($this->oberserverCollection as $oberserver){ //把观察者的集合循环
if($oberserver->name != $beAttackedPlayerName) $oberserver->help($beAttackedPlayerName);//调用各个观察者的救援函数,参数为被攻击的电脑的名字,if用来排除被攻击的电脑的观察者
}
}

abstract public function beAttacked($beAttackedPlayer);
}



//具体的结盟类
class Ally extends abstractAlly {

public function __construct($allPlayerName){ //把所有电脑玩家的数组循环
foreach ($allPlayerName as $playerName){ //增加观察者,参数为各个电脑玩家的名称
$this->addOberserver($playerName);
}
}

public function beAttacked($beAttackedPlayerName){ //将被攻击的电脑的名字通知各个观察者
$this->notify($beAttackedPlayerName); //调用各个观察者的救援函数,参数为被攻击的电脑的名字,if用来排除被攻击的电脑的观察者
}
}



//观察者的接口
interface Ioberserver {
public function help($beAttackedPlayer); //定义规范救援方法
}


//具体的观察者类
class oberserver implements Ioberserver {

public $name; //观察者(也是玩家)对象的名字
public function __construct($name){ //构造函数,参数为观察者(也是玩家)的名称
$this->name = $name;
}

public function help($beAttackedPlayerName){ //观察者进行救援的方法
echo $this->name." help ".$beAttackedPlayerName."<br>"; //这里简单的输出,谁去救谁,最后加一个换行,便于显示
}

}


// 主程序
$allComputePlayer = array('Zerg1', 'Protoss2', 'Zerg2');  //假设我一对三,两家虫族,一家神族
$Ally = new Ally($allComputePlayer); //新建电脑结盟
$Ally->beAttacked('Zerg2'); //假设我进攻了第二个虫族

/*
  执行结果:
  Zerg1 help Zerg2
  Protoss2 help Zerg2
*/


实例二:

/*
*
* 观察者模式是一种非常简单的事件系统,包含了两个或更多的互相交互的类。这一模式允许某个类观察另个类的状态。当被观察者的状态发生改变时就会通知所有观察者进行相应的变化。
在观察者模式中,被观察者称为subject,观察者称为observer,为了表达这些内容,SPL(Standard PHP Libaray)提供了SplSubject和SplObserver两个接口。在编写观察者模式时,只要实现这两个接口即可。
接口如下:
interface SplSubject{
public function attach(SplObserver $observer);//注册观察者
public function detach(SplObserver $observer);//释放观察者
public function notify();//通知所有注册的观察者
}
interface SplObserver{
public function update(SplSubject $subject);//观察者进行更新状态
}
这一模式的概念是SplSubject类维护了一个特定状态,当这个状态发生变化时,它就会调用notify()方法。调用notify()方法时,所有之前使用attach()方法注册的SplObserver实例的update方法都会被调用。
以下是实现代码:
*/

class DemoSubject implements SplSubject {

private $observers, $value;

public function __construct() {
$this->observers = array();
}

public function attach(SplObserver $observer) { //注册观察者
$this->observers[] = $observer;
}

public function detach(SplObserver $observer) { //释放观察者
if($idx = array_search($observer,$this->observers,true)) {
unset($this->observers[$idx]);
}
}

public function notify() { //通知所有观察者
foreach($this->observers as $observer) {
$observer->update($this);
}
}

public function setValue($value) {
$this->value = $value;
$this->notify();
}

public function getValue() {
return $this->value;
}

}

class DemoObserver implements SplObserver {

public function update(SplSubject $subject) {
echo 'The new value is '. $subject->getValue();
}

}

$subject = new DemoSubject();
$observer = new DemoObserver();
$subject->attach($observer);
$subject->setValue(5);

// 输出结果: The new value is 5



参考:

http://dev.21tx.com/2008/10/07/13977.html

http://bbs.php100.com/read-htm-tid-26715.html

posted @ 2012-03-14 00:04  TECS27  阅读(195)  评论(0编辑  收藏  举报