<?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();
#使用觀察者模式,把登入的兩種業務解耦。