forget for get

覚えるために忘れる

Observerパターン

観察対象の状態が変化すると、通知する

 

Subject(被験者):NumberGenerator
 Observerを登録・削除するメソッド、現在の状態を取得するメソッドをもつ
具体的なSubject:RandomNumberGenerator
 状態が変化したらObserverに伝える
Observer(観察者):Observer
具体的なObserver:DigitObserver、GraphObserver
 updateが呼ばれると、Subjectの現在の状態を取得して何か処理をする

 

Observer.php

interface Observer {
  function update(NumberGenerator $generator): void;
}

NumberGenerator.php

abstract class NumberGenerator {
  private $observers = [];
  function addObserver(Observer $observer): void {
    $this->observers[] = $observer;
  }
  function deleteObserver(Observer $observer): void {
    foreach ($this->observers as $key => $val) {
      if ($val == $observer) unset($this->observers[$key]);
    }
  }
  function notifyObservers(): void {
    foreach ($this->observers as $observer) {
      $observer->update($this);
    }
  }
  abstract function getNumber(): int;
  abstract function execute(): void;
}

RandomNumberGenerator.php

class RandomNumberGenerator extends NumberGenerator {
  private $number;
  function getNumber(): int {
    return $this->number;
  }
  function execute(): void {
    for ($i=0;$i<3;$i++) {
      $this->number = rand(1, 20);
      $this->notifyObservers();
    }
  }
}

DigitObserver.php

class DigitObserver implements Observer {
  function update(NumberGenerator $generator): void {
    echo "DigitObserver:" . $generator->getNumber() . "\n";
    sleep(1);
  }
}

GraphObserver.php

class GraphObserver implements Observer {
  function update(NumberGenerator $generator): void {
    $str = "";
    $count = $generator->getNumber();
    for ($i=0;$i<$count;$i++) {
      $str .= "*";
    }
    echo "GraphObserver:" . $str . "\n";
    sleep(1);
  }
}

Main.php

require "../autoload.php";
$generator = new RandomNumberGenerator();
$dObserver = new DigitObserver();
$gObserver = new GraphObserver();
$generator->addObserver($dObserver);
$generator->addObserver($gObserver);
$generator->execute();

autoload.php

function autoload($className){
  require './'.$className.'.php';
}
spl_autoload_register('autoload');