PHP设计模式之观察者模式
先抛出一个问题,你的网站有一个新用户注册,假设你需要给用户发送一条站内信,一封电子邮件,给用户分配一个宠物。
那么假定程序需要4个类,分别是用户类(User),电子邮件类(Email),站内信息类(Message),宠物类(Pet)。
那么要解决上面的问题,我们可以直接在 用户对象中用户注册成功后面计入其他3个对象相应的处理方法。这样目的达到了,是否合理呢?
试想,现在用户类需要改动,有可能就会导致注册成功后的动作不能正常启动,或者我改动了其他3个类,我就必须回到User类中寻找到相应的代码进行修改。这样会造成很多不必要的麻烦,如果是团队协作,那就真是头疼了。
在OOP编程中,我们一直在说一个东西就是避免组件之间紧密耦合。上面给出的解决办法就违反了这一原则。观察者模式提供了避免组件之间紧密耦合的一种方法。
用观察者来分析以上问题:
User一个被观察的对象;
Email,Message,Pet是观察者;
首先观察者需要注册为User的观察者。
一当被观察者有相应的动作,观察者就会作出相应的反映。
代码清单:
//先定义一个用户注册观察者接口
interface IObserver{
public function onChanged();
}
//同上我们需要定义一个被观察者抽象类
abstract class Observable{
//观察者集合
private $_observers;
public function addObserver($observer)
{
$this->_observers=[] = $observer;
}
//通知各个观察者
public function notify();
}
//用户类
class User extends Observable{
public function register()
{
//注册过程省略,这里假定注册成功返回用户ID号($uid);
if($uid) $this->notify($uid);
}
public function notify($uid)
{
foreach ($this->_observers as $os) {
$os->onChanged($uid);
}
}
//....
}
//邮件类
class Email implements IObserver{
//其余代码省略
public function onChanged()
{
$uid = func_get_arg(1);
//根据$uid取得此函数需要的变量$email,$username
//具体代码省略
$this->setEmail($email);
$this->setContent("{$username},欢迎您注册本站!");
$this->send();
}
}
//宠物类
class Pet implements IObserver{
//其余代码省略
public function onChanged()
{
$uid = func_get_arg(1);
$this->setPet($uid);
}
}
//信息类
class Message implements IObserver{
//其余代码省略
public function onChanged()
{
$uid = func_get_arg(1);
$this->sendMsg($uid, '欢迎注册本站!');
}
}
//驱动类
class Drive{
public function main()
{
$user = new User;
//注册观察者
$user->addObserver( new Email() );
$user->addObserver( new Message() );
$user->addObserver( new Pet() );
$user->register();
}
}
$drive = new Drive;
$drive->main();
POSTED ON 2010年06月14日,