m-chris 发表于 2019-7-22 10:20

基于PHP SPL的观察者模式

本帖最后由 m-chris 于 2019-7-22 10:36 编辑

PS:第一次发帖还有点小激动,如有哪里写的不对的,还请指教.      
      观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
      这其实可以用于在一个对象发生变化时,其他依赖它的对象都得到通知并自动更新.
      下面上代码,LOGIN类是被观察者,实现了SplSubject接口,这个接口用于验证登录是否正确,如果正确,则LOGIN_SUCCESS, 如果用户名密码错误,则LOGIN_WRONG,其他错误LOGIN_UNKNOWN.
文件名Login.php

include './LoginObserver.php';
session_start();
class Login implements SplSubject{
    private $storage;
    private $username = 'chris';
    private $password = '123456';
    public $status ;
    const LOGIN_SUCCESS = 1;
    const LOGIN_WRONG = 2;
    const LOGIN_UNKNOWN = 3;
    function __construct()
    {
      $this->storage = new SplObjectStorage();
      if(!isset($_SESSION['login_wrongnum'])){
            $_SESSION['login_wrongnum'] = 0;
      }
    }
    function attach(SplObserver $observer){
      $this->storage->attach($observer);
    }
    function detach(SplObserver $observer)
    {
      $this->storage->detach($observer);
    }
    function notify(){
      foreach($this->storage as $obs){
            $obs->update($this);
      }
    }
    function loginhandle(){
      //增加观察者
      $this->attach(new EmailObserver);
      $this->attach(new WriteObserver);
      $ip = '127.0.0.1';
      $username = isset($_GET['username']) ? $_GET['username'] : '';
      $password = isset($_GET['password']) ? $_GET['password'] : '';
      if($username!= $this->username || $password!=$this->password){
            $this->setStatus(self::LOGIN_WRONG,$ip);
            $_SESSION['login_wrongnum'] = $_SESSION['login_wrongnum']+1;
            $check = false;
      }else{
            $this->setStatus(self::LOGIN_SUCCESS,$ip);
            $check = true;
      }
      $this->notify();
      return $check;
    }
    public function setStatus($status,$ip){
      $this->status = $status;
      $this->ip = $ip;
    }
    public function getStatus(){
      return $this->status;
    }
}
$login = new Login;


#下面是两个观察者,邮件观察者和写观察者,其中邮件观察者是当输入错误3次以上将以发送邮件并禁用该用户,而写观察者只要用户名密码不正确就会输出,这里只是伪代码以echo进行展示,具体逻辑请各位看管自己补充完整文件名:LoginObserver.php

<?php
class EmailObserver implements SplObserver{
    public function update(SplSubject $subject)
    {
      if($_SESSION['login_wrongnum']>2 ){
            echo "登录错误超过3次,账户已禁用并已经给管理员发送邮件!\n";
      }
    }
}

class WriteObserver implements SplObserver{
    public function update(SplSubject $subject){
      if($subject->status == 1 && $_SESSION['login_wrongnum']<2){
            echo "登录成功!";
      }else if($subject->status == 1 && $_SESSION['login_wrongnum']>2){
            echo "记录日志:虽然用户名密码正确,但是已经连续输入几次错误\n";
      }else{
            echo "记录日志:连续输入多次错误密码";
      }
    }
}
页: [1]
查看完整版本: 基于PHP SPL的观察者模式