Skip to content

Instantly share code, notes, and snippets.

@Kcko

Kcko/observer.php

Last active Apr 10, 2020
Embed
What would you like to do?
<?php
/*
Definice
---------
Návrhový vzor Observer definuje závislost 1:n mezi subjektem a libovolným počtem
pozorovatelů. Při změně stavu subjektu jsou o této skutečnosti automaticky informovány
všechny pozorovatele.
Pro implementaci tohoto návrhového vzoru jsou nutné následující kroky:
1. Definovat rozhraní (Observer) pro pozorovatele, které vyžaduje jednu
metodu, prostřednictvím níž jsou pozorovatelé informovaní o změně stavu
objektu.
2. Definovat rozhraní (Observable) pro pozorované objekty. Toto rozhraní
musí vyžadovat metody na přidání a odstranění pozorovatelů a také metodu
notify(), pomocí níž jsou pozorovatele informovány o změně stavu
pozorovaného objektu. rozdílem. Pozorovatel žádné hodnoty týkající se pozorovaného objektu – je bezstavový. Tento pozorovatel
tedy může současně pozorovat více objektů. Pozorovatel naopak uchovává informaci, kdy má nastat další pravidelná kontrola – uchovává
určitý stav. Protože se tato hodnota může u různých tiskáren lišit, lze jej použít
jen pro pozorování jednoho objektu. Pro každý další objekt je nutné vytvořit nový objekt pozorovatele.
3. V pozorovaném objektu implementovat rozhraní Observable.
4. Do metod, které mění stav objektu, vložit volání metody notify().
5. Implementovat konkrétní pozorovatele.
*/
interface Printer
{
public function turnOn();
public function turnOff();
public function printPublication(Publication $p, $count = 1);
public function getType();
public function getPageCounter();
}
interface Observable
{
public function attach(Observer $observer);
public function detach(Observer $observer);
public function notify();
}
interface Observer
{
public function update(Observable $observable);
}
class LaserPrinter implements Printer, Observable
{
protected $turnedOn = false;
protected $type = null;
protected $pageCounter = 0;
protected $observers = array();
function __construct($type)
{
$this->type = $type;
}
public function turnOn()
{
$this->turnedOn = true;
}
public function turnOff()
{
$this->turnedOff = false;
}
public function getType()
{
return $this->type;
}
public function printPublication(Publication $p, $count = 1)
{
if (true !== $this->turnedOn) {
return false;
}
$pageCount = $p->getPageCount();
$this->pageCounter += $pageCount * $count;
// 2 OBSERVER
$this->notify();
return true;
}
public function getPageCounter()
{
return $this->pageCounter;
}
// OBSERVE THINGS
public function attach(Observer $observer)
{
$this->observers[] = $observer;
}
public function detach(Observer $observer)
{
$this->observers = array_diff($this->observers, array($observer));
}
public function notify()
{
foreach($this->observers as $observer)
{
$observer->update($this);
}
}
}
class ObserverInitialCheck implements Observer
{
protected $checkPageCounter;
public function __construct($pageCounter = 10000)
{
$this->checkPageCounter = $pageCounter;
}
public function update(Observable $observable)
{
if (!$observable instanceof Printer) {
return;
}
if ($observable->getPageCounter() >= $this->checkPageCounter) {
printf(
"Nutná prvotní kontrola po %d vytištěných stranách.\n",
$this->checkPageCounter
);
$observable->detach($this);
}
}
}
$book = new Book('PC', 580);
$printer = new LaserPrinter('Printer 1');
$initialCheck = new ObserverInitialCheck(10000);
$printer->attach($initialCheck);
$printer->turnOn();
$printer->printPublication($book, 10);
printf("Počet vytištěných stran: %d\n",
$printer->getPageCounter());
$printer->printPublication($book, 10);
printf("Počet vytištěných stran: %d\n",
$printer->getPageCounter());
$printer->turnOff();
/*
Počet vytištěných stran: 5800
Nutná prvotní kontrola po 10000 vytištěných stranách.
Počet vytištěných stran: 11600
*/
class ObserverRegularCheck implements Observer
{
protected $nextCheck = null;
protected $interval;
public function __construct($start, $interval)
{
$this->nextCheck = $start;
$this->interval = $interval;
}
public function update(Observable $observable)
{
if (!$observable instanceof Printer) {
return;
}
if ($observable->getPageCounter() >= $this->nextCheck)
{
printf(
"Pravidelná kontrola po %d vytištěných stranách.\n",
$this->nextCheck
);
$this->nextCheck += $this->interval;
}
}
}
$book = new Book('PC', 580);
$printer = new LaserPrinter('Printer 1');
$initialCheck = new ObserverInitialCheck(10000);
$regularCheck = new ObserverRegularCheck(40000, 30000);
$printer->attach($initialCheck);
$printer->attach($regularCheck);
$printer->turnOn();
$printer->printPublication($book, 20);
printf("Počet vytištěných stran: %d\n",
$printer->getPageCounter());
$printer->printPublication($book, 60);
printf("Počet vytištěných stran: %d\n",
$printer->getPageCounter());
$printer->printPublication($book, 50);
printf("Počet vytištěných stran: %d\n",
$printer->getPageCounter());
$printer->turnOff();
/*
Nutná prvotní kontrola po 10000 vytištěných stranách.
Počet vytištěných stran: 11600
Pravidelná kontrola po 40000 vytištěných stranách.
Počet vytištěných stran: 46400
Pravidelná kontrola po 70000 vytištěných stranách.
Počet vytištěných stran: 75400
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.