//以一个购物流程为例子 class order { protected $observers = array(); // 存放观察容器 //观察者新增 public function addObServer($type, $observer) { $this->observers[$type][] = $observer; } //运行观察者 public function obServer($type) { if (isset($this->observers[$type])) { foreach ($this->observers[$type] as $obser) { $a = new $obser; $a->update($this); //公用方法 } } } //下单购买流程 public function create() { echo '购买成功'; $this->obServer('buy'); // buy动作 } } class orderEmail { public static function update($order) { echo '发送购买成功一个邮件'; } } class orderStatus { public static function update($order) { echo '改变订单状态'; } } $ob = new order; $ob->addObServer('buy', 'orderEmail'); $ob->addObServer('buy', 'orderStatus'); $ob->create(); 作者:initphp
最近我被要求集成第三方论坛软件到一个现有的门户网站。问题是,两个应用程序有自己的单独的身份验证机制。从用户的角度来看,这是非常理想的用户登录到门户不必登录到论坛分别。在这种情况下,我不想修改论坛代码不必要因为它会创建一个维护的噩梦——我不得不合并任何后续更新和bug修复从供应商和小心不要覆盖我的修改。这就是观察者模式来为我派上用场。
在本文中,我将向您展示如何实现观察者模式。您将学习如何在各种类模式涉及到另一个作为主体和观察员,怎么话题通知观察者的改变它的状态,以及如何识别场景,这将是适合使用观察者模式在您自己的代码。
(在这篇文章中,将展示如何实现观察者模式。)
观察者模式
观察者模式(也称为发布-订阅模式)是一种行为的设计模式,它定义了对象之间的一对多关系,这样,当一个对象改变状态,所有依赖对象和自动更新通知。在我的例子中,我使用这个模式来链接门户的身份验证机制与论坛软件。该法案的登录到门户也自动触发用户是登录到论坛一样。
一个对象与其他对象的一对多关系感兴趣的状态称为主题或出版商。其依赖的对象被称为观察员或用户。这个观察人士通知每当状态的变化,可以采取相应的主题。这个主题可以有任意数量的依赖观察者,它通知,和任意数量的观察员可以订阅主题收到这样的通知。
观察者类
观察者类(Observer class)提供了一个 update() 方法将被调用, 以通知的主题目标对象(subject)的状态变化。 在这个例子中,我定义了update()方法作为一个具体的方法。 如果你喜欢,你可以定义为抽象(abstract)的方法在这里,然后提供一个具体的实现,它在你的观察者的子类。
<?php
abstract class Observer
{
public function __construct($subject = null) {
if (is_object($subject) && $subject instanceof Subject) {
$subject->attach($this);
}
}
public function update($subject) {
// looks for an observer method with the state name
if (method_exists($this, $subject->getState())) {
call_user_func_array(array($this, $subject->getState()), array($subject));
}
}
}
构造() ( __construct() ) 方法接受一个实例的一个看得见的主题和附着主题——我将会看到。 update()方法检索主题的当前状态,并使用它来调用子类observer方法名称相同的状态。
所以,在我的具体情况,我需要使门户现有的身份验证类的主题和创建一个具体观察者子类嵌入论坛的验证代码。我还需要子类实现方法使用主体的国家。
主题类 (The Subject Class)
主题类也是一个抽象类, 定义了四种主要方法: attach()、detach(), setState() 和 notify()。 为了方便起见,我还添加了getObservers() 和 getState()方法在这里。
<?php
abstract class Subject
{
protected $observers;
protected $state;
public function __construct() {
$this->observers = array();
$this->state = null;
}
public function attach(Observer $observer) {
$i = array_search($observer, $this->observers);
if ($i === false) {
$this->observers[] = $observer;
}
}
public function detach(Observer $observer) {
if (!empty($this->observers)) {
$i = array_search($observer, $this->observers);
if ($i !== false) {
unset($this->observers[$i]);
}
}
}
public function getState() {
return $this->state;
}
public function setState($state) {
$this->state = $state;
$this->notify();
}
public function notify() {
if (!empty($this->observers)) {
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
}
public function getObservers() {
return $this->observers;
}
}