观察者模式

目录 设计模式

观察者模式属于行为型模式
概述:观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象(主体)的状态发生改变时,所有依赖它的对象(观察者)都得到通知并自动更新
它完美的将观察者对象和被观察者对象分离。可以在独立的对象(主体)中维护一个对主题感兴趣的依赖项(观察者)列表。让所有观察者各自实现公共的Observer接口,以取消主体和依赖项的直接依赖关系。

<?php
/**
 * 主题功能
 */
class Observable{
 
 /**
  * 添加观察者
  */
 function attact (Observer $observer);
 
 /**
  * 删除观察者
  */
 function detach (Observer $observer);
 
 /**
  * 通知观察者
  */
 function notify ();
}
<?php
/**
 * 主体类
 * 被观察者
 */
class Login implements Observable{
 
 /**
  *密码错误状态
  */
 const LOGIN_ACCESS = 1;
 const LOGIN_WRONG_PASS = 2;
 const LOGIN_USER_UNKNOWN = 3;
 /**
  *登录时的状态
  *
  */
 private $loginstatus;
 
 /**
  *观察者列表
  *@var array
  */
 private $observers;
 
 /**
  *构造方法
  *
  */
 public function __construct(){
  $this->observers = array();
 }
 
 /**
  *添加观察者
  *@param $observer Observer object
  */
 public function attach( Observer $observer ){
  $this->observers[] = $observer;
 }
 
 /**
  *删除观察者
  *@param $observer Observer object
  */
 public function detach( Observer $observer ){
  $newobservers = array();
  foreach( $this->observers as $obs ){
   if( $obs != $observer ){
    $newobservers[] = $observer;
   }
  }
  $this->observers = $newobservers;
 }
 
 /**
  *通知观察者
  *
  */
 public function notify(){
  foreach( $this->observers as $obs ){
   $obs->update( $this );
  }
 }
 
 /**
  *处理登录
  *@param $user string 用户名
  *@param $pass string 密码
  *@param $ip string IP地址
  */
 public function handleLogin( $user='li.yonghuan', $pass='123456', $ip='127.0.0.1' ) {
  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_UNKNOWN, $user, $ip );
    $ret = false;
    break;
  }
  $this->notify();
  return $ret;
 }
 
 /**
  *设置状态值
  *@param $status string 状态值
  *@param $user string 用户名
  *@param $ip string IP地址
  */
 public function setStatus( $status, $user, $ip ) {
  $this->loginstatus = array( $status, $user, $ip );
 }
 
 
 /**
  *获取状态
  *登录时产生的各种状态
  */
 public function getStatus() {
 
  return $this->loginstatus;
 }  
}
<?php
/**
 *接口:观察者
 */
interface Observer {
    /**
     *更新
     */
    function update( Observable $observable );
}
<?php
/**
 *抽象类,登录观察者
 */
abstract class LoginObserver implements Observer {
    /**
     *Login 对象
     *@var Login object
     */
    private $login;
 
    /**
     *构造方法
     *@param $login Login object
     */
    public function __construct( Login $login ) {
       $this->login = $login;
       $login->attach( $this );
    }
 
    /**
     *更新操作
     *@param $observer Observer
     */
    public function update( Observable $observable ) {
        if( $observable === $this->login ) {
            $this->doUpdate( $observable );
        }
    }
 
    /**
     *执行更新
     *@param login Login
     */
    abstract function doUpdate( Login $login );
 
}
<?php
/**
 *安全监控登录,负责登录安全的观察者
 */
class SecurityMonitor extends LoginObserver {
    /**
     *执行更新
     *@param $login Login
     */
    public function doUpdate( Login $login ) {
       $status = $login->getStatus();
       if( $status[0] == Login::LOGIN_WRONG_PASS ) {
           //发送邮件给系统管理员
           print __CLASS__.":\tsending mail to sysadmin";
       }
    }
}
<?php
/**
 *正确登录,观察者
 */
class GeneralLogger extends LoginObserver {
   /**
    *观察者更新
    *
    */
    public function doUpdate( Login $login ) {
        $status = $login->getStatus();
       if( $status[0] == Login::LOGIN_ACCESS ) {
           //记录登录数据到日志
           print __CLASS__.":\tadd login data to log";
       }
    }
}
<?php
/**
 *用户名错误,观察者
 */
class UserMonitor extends LoginObserver {
   /**
    *观察者更新
    *
    */
    public function doUpdate( Login $login ) {
        $status = $login->getStatus();
       if( $status[0] == Login::LOGIN_USER_UNKNOWN ) {
           //用户名错误
           print __CLASS__.":\tusername is uncorrect";
       }
    }
}
<?php
 /**
 * 观察者模式
 */
public function actionObserver(){

 Yii::import('ext.observer.*');
    $login = new Login();
    //添加安全观察者
    $login->attach(new SecurityMonitor( $login ));
   
    //添加正确登录观察者
    $login->attach(new GeneralLogger( $login ));
   
    //添加用户名观察者
    $login->attach(new UserMonitor( $login ));
    $login->handleLogin();

暂无评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注