Pattern: 觀察者模式
Class Diagram: Line群組通知
情境:讓我們用Line群組,來實作觀察者模式
其中會有接收到主題類別通知時的更新方法 (具體實作內容由子類決定)。
1 2 3 4 5 6 7 8
| <?php
namespace App\ObserverPattern\LineGroup;
abstract class Observer { abstract public function update(); }
|
它會有新增觀察者、移除觀察者、通知觀察者的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?php
namespace App\ObserverPattern\LineGroup;
use App\ObserverPattern\LineGroup\Observer;
abstract class Subject {
protected $observers = [];
public function attachObserver(Observer $observer) { $this->observers[] = $observer; }
public function detachObserver(Observer $observer) { $index = array_search($observer, $this->observers);
if ($index >= 0) { unset($this->observers[$index]); } }
public function notifyObservers() { foreach ($this->observers as $observer) { $observer->update(); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php
namespace App\ObserverPattern\LineGroup;
use App\ObserverPattern\LineGroup\Observer;
class User extends Observer { protected $name;
public function __construct($name) { $this->name = $name; }
public function update() { } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <?php
namespace App\ObserverPattern\LineGroup;
use App\ObserverPattern\LineGroup\Subject; use App\ObserverPattern\LineGroup\User;
class Program extends Subject { protected $state = 'nothing new';
public function run() { $bear = new User('Bear'); $this->attachObserver($bear);
$this->notifyObservers();
$jane = new User('Jane'); $this->attachObserver($jane);
$this->notifyObservers();
$this->state = 'new message'; $this->notifyObservers(); $this->state = 'nothing new';
$this->detachObserver($jane);
$this->notifyObservers(); } }
|
[單一職責原則]
我們將主題類別 (Subject) 與 觀察者類別 (Observer) 視作兩種不同的職責。
目前範例尚未將聊天室的職責與通知的職責分離。
[開放封閉原則]
當新增新的主題類別時,我們可以輕易地新增、移除、通知對應觀察者。
亦可以新增新的觀察者類別,再將其加入既有的主題類別。
[裡氏替換原則]
透過子類來定義觀察者類別中更新方法具體的實作。
目前範例的缺點是,觀察者類別不好對更新方法取更適合的命名。
[依賴反轉原則]
抽象主題類別依賴於抽象的觀察者類別。
使用者類別實作抽象的觀察者類別。
主題類別不必知道具體觀察者想做什麼,
僅需知道觀察者類別有接口可以通知更新。
ʕ •ᴥ•ʔ:架構容易,細節仍需琢磨的模式。