设计模式 - 结构 - 观察者模式

观察者模式

  • 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式

  • 在开始之前我们需要了解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)或对象的集合、但是它所存放的对象都是唯一的
  • 代码

      // 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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!