PHP 設計模式之——觀察者模式

waterandair發表於2019-02-16
<?php
/**
 * Created by waterAndAir
 * title: 觀察者模式
 * Date: 2016/12/21
 * Time: 15:57
 */

/**
 * 被觀察者
 * SplSubject :The SplSubject interface is used alongside SplObserver to implement the Observer Design Pattern.
 * SplSubject介面用於與SplObserver實現觀察者設計模式
 * Class User
 */
class User implements SplSubject{
  public $lognum;       //使用者登入次數限制
  public $hobby;        //使用者愛好

  protected $observers = null;       //存放觀察者“們”

  public function __construct($hobby)
  {
    $this->lognum = rand(1, 10);    //實際應用中,這裡應該是從快取或資料庫中讀取的資料
    $this->hobby = $hobby;          //實際應用中,這裡應該是從快取或資料庫中讀取的資料
    $this->observers = new SplObjectStorage();    //儲存一組物件
  }

  public function login(){
    //todo:操作session
    $this->notify();
  }

  /**
   * 實現介面函式,用於新增一個“觀察者”
   * @param SplObserver $observer
   */
  public function attach(SplObserver $observer)
  {
    $this->observers->attach($observer);
  }

  /**
   * 實現介面函式,用於刪除一個“觀察者”
   * @param SplObserver $observer
   */
  public function detach(SplObserver $observer)
  {
    $this->observers->detach($observer);
  }

  /**
   * 實現介面函式,用於通知觀察者
   */
  public function notify()
  {
    $this->observers->rewind();                    //指標指到第一位
    while($this->observers->valid()){             //不斷獲取有效物件
      $observer = $this->observers->current();     //獲取當前物件
      $observer->update($this);                    //觀察者處理業務
      $this->observers->next();                    //移動指標到下一物件
    }
  }
}

/**
 * 一個觀察者 :負責登入安全驗證
 * Class Security
 */
class Security implements SplObserver{
  public function update(SplSubject $subject)
  {
    if($subject->lognum < 3){
      echo  "這是第".$subject->lognum."次安全登入";
    }else{
      echo  "這是第".$subject->lognum."次異常登入";
    }
  }
}

/**
 * 另一個觀察者 :負責獲取使用者特徵
 * Class Character
 */
class Character implements SplObserver{
  public function update(SplSubject $subject){
    echo $subject->hobby."是個非常不錯的愛好";
  }
}


//測試

$user = new User(`學習`);
$user->attach(new Security());
$user->attach(new Character());
$user->login();


#使用觀察者模式,把登入的兩種業務解耦。

相關文章