PHP實現觀察者模式SplSubject SplObserver SplObjectStorage

3333333_ 發表於 2020-11-21
PHP
“觀察者模式”的觀察者三個字資訊量很大。玩過很多網路遊戲的童鞋們應該知道,即便是鬥地主,除了玩家,還有一個角色叫“觀察者"。在我們今天他談論的模式設計中,觀察者也是如此。首先,要有一個“主題”。只有有了一個主題,觀察者才能搬著小板凳兒聚在一堆。其次,觀察者還必須要有自己的操作。否則你聚在一堆兒沒事做也沒什麼意義。
   從程式導向的角度來看,首先是觀察者向主題註冊,註冊完之後,主題再通知觀察者做出相應的操作,整個事情就完了。
   從物件導向的角度來看,主題提供註冊和通知的介面,觀察者提供自身操作的介面。(這些觀察者擁有一個同一個介面。)觀察者利用主題的介面向主題註冊,而主題利用觀察者介面通知觀察者。耦合度相當之低。
         如何實現觀察者註冊?通過前面的註冊者模式很容易給我們提供思路,把這些物件加到一棵註冊樹上就好了嘛。如何通知?這就更簡單了,對註冊樹進行遍歷,讓每個物件實現其介面提供的操作

<?php
class User implements SplSubject{
	public $loginNum;
	public $hobby;
	protected $observers=null;
	public function __construct($hobby){
		$this->loginNum=rand(1,10);
		$this->hobby=$hobby;
		$this->observers=new SplObjectStorage();
	}
	public function attach(SplObserver $observer)
	{
		$this->observers->attach($observer);
	}
	public function detach(SplObserver $observer)
	{
		$this->observers->dettach($observer);
		
	}
	public function notify()
	{
		$this->observers->rewind();
		while ($this->observers->valid()) {
			$observer=$this->observers->current();
			$observer->update($this);
			$this->observers->next();
		}
		
	}
	public function longin()
	{
		$this->notify();
	}
}

class Security  implements SplObserver
{
	public function update(SplSubject $subject)
	{
		if($subject->loginNum<3){
			echo "這是您第{$subject->loginNum}次安全登入!\n";
		}else{
			echo "這是您第{$subject->loginNum}次異常登入!\n";
		}
	}
}

class Ad implements SplObserver
{
	public function update(SplSubject $subject)
	{
		if($subject->hobby=='sport'){
			echo "籃球世錦賽門票預訂\n";		
		}else{
			echo "好好學習天天向上\n";
		}
	}
}

class Student implements SplObserver{
	public function update(SplSubject $subject)
	{
		if($subject->hobby=='sport'){
			echo "這是您第{$subject->loginNum}次安全登入!\n";		
		}else{
			echo "好好學習天天向上\n";
		}
	}
}

#實施觀察 

$user =  new User('sutudy');

$observer1 = new Security();
$observer2 = new Ad();

$user->attach($observer1);
$user->attach($observer2);

$user->longin();