设计模式 - 结构 - 观察者模式
观察者模式
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式
在开始之前我们需要了解SPL(php标准库)的SplSubject、SplObserver、SplObjectStorage三个接口
- SplSubject一共有三个方法
interface SplSubject { /* Methods */ // 添加一个观察者 public attach(SplObserver $observer): void // 移除一个观察者 public detach(SplObserver $observer): void // 通知观察者 public notify(): void }
- SplObserver
// 当SplSubject目标触发notify()方法时,被添加到SplSubject里面的观察者将需要执行update方法 public SplObserver::update(SplSubject $subject): void
- SplObjectStorage类实现了以对象为键的映射(map)或对象的集合、但是它所存放的对象都是唯一的
- SplSubject一共有三个方法
代码
// User.php namespace Behavioral\Observer; use SplObjectStorage; use SplSubject; use SplObserver; class User implements SplSubject { private SplObjectStorage $observers; public string $name; public static $i; public function __construct($name) { $this->observers = new SplObjectStorage(); $this->name = $name; } public function attach(SplObserver $observer): void { $this->observers->attach($observer); } public function detach(SplObserver $observer): void { $this->observers->detach($observer); } public function notify(): void { foreach ($this->observers as $observer) { $observer->update($this); } } public function changeMail(string $email) { $this->notify(); } public static function download() { return static::$i++; } } // UserObserver.php namespace Behavioral\Observer; use SplObserver; use SplSubject; class UserObserver implements SplObserver { private array $arrSub = []; public function update(SplSubject $subject): void { //echo $subject->name; //do something //$subject::download(); $this->arrSub[] = clone $subject; } public function getCount(SplSubject $subject): array { return $this->arrSub; } }
// ObserverTest.php namespace Tests; use PHPUnit\Framework\TestCase; use Behavioral\Observer\User; use Behavioral\Observer\UserObserver; class ObserverTest extends TestCase { public function testOs() { $user = new User('Test'); $uo1 = new UserObserver(); $uo2 = new UserObserver(); $user->attach($uo1); $user->attach($uo2); //$user->notify(); $user->changeMail('alex@gmail'); $this->assertEquals(2, $user::$i); } public function testOs2() { $user = new User('Test2'); $uo = new UserObserver(); $user->attach($uo); //$user->notify(); $user->changeMail('alex@gmail'); $this->assertCount(1, $uo->getCount($user)); } }
本作品采用《CC 协议》,转载必须注明作者和本文链接