uml图
代码实现
<?php interface Observable{ function attach(Observer $observer); function detach(observer $observer); function notify(); } //主体 class Login implements Observable { protected $observers; private $status = array(); const LOGIN_USER_UNKNOW = 1; const LOGIN_WRONG_PASS = 2; const LOGIN_ACCESS = 3; function handleLogin($user,$pass,$ip) { switch (rand(1,3)) { case 1: $this->setStatus(self::LOGIN_ACCESS,$user,$ip); $ret = true; break; case 2: $this->setStatus(self::LOGIN_WRONG_PASS,$user,$ip); $ret = false; break; case 3: $this->setStatus(self::LOGIN_USER_UNKNOW,$user,$ip); $ret = false; break; } $this->notify(); return $ret; } private function setStatus($status,$user,$ip){ return $this->status = array($status,$user,$ip); } function getStatus(){ return $this->status; } function __construct() { $this->observers = array(); } function attach(Observer $observer) { $this->observers[] = $observer; } function detach(Observer $observer) { $newobservers = array(); foreach ($this->observers as $obs){ if($obs!==$observer){ $newobservers[] = $obs; } } $this->observers = $newobservers; } function notify(){ foreach ($this->observers as $obs) { $obs->update($this); } } } interface Observer { function update(Observable $observable); } //LoginObserver类负责保证继承该类的观察者使用的主体是Log类型,并将自己添加到主体上 abstract class LoginObserver implements Observer { private $login; function __construct(Login $login){ $this->login = $login; $login->attach($this); } function update(Observable $observable) { if($observable === $this->login){ $this->doUpdate($observable); } } protected abstract function doUpdate(Login $login); } class SecurityMonitor extends LoginObserver { function doUpdate(Login $login) { $status = $login->getStatus(); //发送邮件给系统管理员 echo __CLASS__.": sending mail to sysadmin<br>"; } } class GeneralLogger extends LoginObserver { function doUpdate(Login $login) { $status = $login->getStatus(); //记录登录数据到日志 echo __CLASS__.": add login data to log<br>"; } } class PartnershipTool extends LoginObserver { function doUpdate(Login $login) { $status = $login->getStatus(); //检查IP地址 //如果匹配列表则设置cookie echo __CLASS__.": set cookie if Ip matchers a list<br>"; } } //client //$log = new Login(); //$login->attach(new SecurityMonitor()); $log = new Login(); new SecurityMonitor($log);//加入观察者 new GeneralLogger($log);//加入观察者 new PartnershipTool($log);//加入观察者 $log->notify(); ?>