<?php
// Iterator
/*
Definice
--------
Návrhový vzor Iterator umožňuje sekvenčně přistupovat k prvkům složených objektů
bez zveřejnění jejich základní struktury.
Pro využití návrhového vzoru Iterator jsou nutné následující kroky:
1. Zvolit, zda má třída implementovat rozhraní Iterator, nebo rozhraní
IteratorAggregate.
2. Implementovat metody vyžadované zvoleným rozhraním.
*/
include '1.php';
class BookList implements \Iterator
{
protected $bookDefinitions = array();
protected $books = array();
protected $position = 0;
public function __construct($csvFile)
{
if (!file_exists($csvFile))
{
throw new IOException();
}
$fp = fopen($csvFile, 'r');
while (false != ($line = fgetcsv($fp, 1024, ';'))) {
$this->bookDefinitions[] = array(
'category' => $line[0],
'pagecount' => $line[1]
);
}
}
public function getBook($position)
{
if ($position > count($this->bookDefinitions)) {
throw new Exception();
}
if (!isset($this->books[$position])) {
$this->books[$position] = new Book(
$this->bookDefinitions[$position]['category'],
$this->bookDefinitions[$position]['pagecount']
);
}
return $this->books[$position];
}
public function countBooks()
{
return count($this->bookDefinitions);
}
public function current()
{
if (!isset($this->books[$this->position])) {
$this->books[$this->position] = new Book(
$this->bookDefinitions[$this->position]['category'],
$this->bookDefinitions[$this->position]['pagecount']
);
}
return $this->books[$this->position];
}
public function key()
{
return $this->position;
}
public function next()
{
$this->position++;
}
public function rewind()
{
$this->position = 0;
}
public function valid()
{
if ($this->position < count($this->bookDefinitions))
{
return true;
}
return false;
}
}
$list = new BookList('ext/books.csv');
// 1
for ($j = 0; $j < $list->countBooks(); $j++)
{
$book = $list->getBook($j);
printf("%d -> %s\n", $j, $book->getCategory());
}
echo PHP_EOL;
// 2
$list->rewind();
while ($list->valid())
{
$position = $list->key();
$book = $list->current();
printf("%d -> %s\n", $position, $book->getCategory());
$list->next();
}
echo PHP_EOL;
// 3
foreach($list as $position => $book)
{
printf("%d -> %s\n", $position, $book->getCategory());
}
// 4
class ListHelper
{
public static function displayBooks(\Traversable $list)
{
foreach($list as $position => $book)
{
printf("%d -> %s\n", $position, $book->getCategory());
}
}
}
echo PHP_EOL;
$list = new BookList('ext/books.csv');
ListHelper::displayBooks($list);
echo PHP_EOL;
// chceme iterator pouzit i na pole
$books = array(
new Book('PC', '100'),
new Book('MEDICINA', '400'),
new Book('AUTO-MOTO', '350'),
);
// takhle to nejde bze to neni Traversable
//ListHelper::displayBooks($books);
// takhle to pujde
ListHelper::displayBooks(new ArrayIterator($books));
<?php
// Visitor
/*
Definice
--------
Návrhový vzor Visitor vám umožní přidat nové operace do struktury objektů bez
změny prvků této struktury. Operace, které se mají v této struktuře provést, jsou
zapouzdřené do nové třídy.
Pro vytvoření a použití návštěvníka i v jiných situacích jsou nutné následující
kroky:
1. Analyzovat, jaké typy prvků, které chcete rozšířit o nové funkce, se nacházejí
ve struktuře objektů.
2. Definovat rozhraní pro objekt návštěvníka s deklaracemi metod visit*()
pro každý typ prvku.
3. Do každé třídy, která se používá ve struktuře objektů, přidat metodu
acceptVisitor(), která přijme objekt implementující rozhraní z bodu 2.
V této metodě zavolat příslušnou metodu visit*() objektu návštěvníka
a předat jí aktuální objekt.
4. Projít všechny objekty, na které odkazuje aktuální objekt (poduzly), a jejich
metodě acceptVisitor()předat objekt návštěvníka.
*/
interface Publication
{
// ... stávající metody rozhraní
public function acceptVisitor(Visitor $visitor);
}
interface Visitor
{
public function visitLibrary(Library $library);
public function visitRentalAction(RentalAction $rentalAction);
public function visitPublication(Publication $publication);
public function visitMember(Member $member);
}
class Library
{
// ... atributy a metody třídy
public function acceptVisitor(Visitor $visitor)
{
$visitor->visitLibrary($this);
foreach ($this->rentalActions as $rentalAction)
{
$rentalAction->acceptVisitor($visitor);
}
}
}
class RentalAction
{
// ... atributy a metody třídy
public function acceptVisitor(Visitor $visitor)
{
$visitor->visitRentalAction($this);
$this->publication->acceptVisitor($visitor);
$this->member->acceptVisitor($visitor);
}
}
class Member
{
// ... atributy a metody třídy
public function acceptVisitor(Visitor $visitor)
{
$visitor->visitMember($this);
}
}
class VisitorEcho implements Visitor
{
public function visitLibrary(Library $library)
{
print "Knihovna\n";
}
public function visitRentalAction(RentalAction $rentalAction)
{
printf(" + Publikace vypůjčená od %s", $rentalAction->getRentDate());
if ($rentalAction->isReturned()) {
printf(" do %s\n", $rentalAction->getReturnDate());
} else {
print " - dosud nevrácena\n";
}
}
public function visitPublication(Publication $publication)
{
printf(" - Kategorie: %s\n", $publication->getCategory());
printf(" - Počet stran: %d\n", $publication->getPageCount());
}
public function visitMember(Member $member)
{
printf(" - Čtenář: %s\n", $member->getName());
}
}
$visitor = new VisitorEcho();
$library->acceptVisitor($visitor);
<?php
class VisitorXMLExport implements Visitor
{
protected $doc;
protected $root;
protected $currentAction = null;
public function __construct()
{
$this->doc = new \DOMDocument('1.0', 'UTF-8');
$this->doc->formatOutput = true;
}
public function visitLibrary(Library $library)
{
$this->root = $this->doc->createElement('library');
$this->doc->appendChild($this->root);
}
public function visitRentalAction(RentalAction $rentalAction)
{
$this->currentAction = $this->doc->createElement('rentalAction');
$this->root->appendChild($this->currentAction);
$this->currentAction->setAttribute(
'rentDate',
$rentalAction->getRentDate()
);
if ($rentalAction->isReturned()) {
$this->currentAction->setAttribute(
'returnDate',
$rentalAction->getReturnDate()
);
}
}
public function visitPublication(Publication $publication)
{
$tag = $this->doc->createElement('publication');
$tag->setAttribute('category', $publication->getCategory());
$tag->setAttribute('pageCount', $publication->getPageCount());
$this->currentAction->appendChild($tag);
}
public function visitMember(Member $member)
{
$tag = $this->doc->createElement('member');
$tag->setAttribute('id', $member->getId());
$tag->setAttribute('name', $member->getName());
$this->currentAction->appendChild($tag);
}
public function asXML()
{
return $this->doc->saveXML();
}
}
$visitor = new VisitorXMLExport();
$library->acceptVisitor($visitor);
print $visitor->asXML()
<?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
*/
<?php
/*
Definice
Návrhový vzor Command zapouzdřuje jednotlivé požadavky jako objekty. Díky
tomu lze parametrizovat jiné objekty s požadavky, přidávat požadavky do fronty
a podporovat operace, které je možné provádět zpětně.
Pro implementaci tohoto návrhového vzoru jsou nutné následující kroky:
1. Definovat rozhraní pro jednotlivé příkazy.
2. Vytvořit konkrétní příkazy, které implementují rozhraní z bodu 1 a ve třídě
zapouzdřují jednotlivé požadavky.
3. Vytvořit způsob, který umožní
*/
// BAD
interface PublishingProcess {
public function publish(Publication $publication);
}
class PrintedBook implements PublishingProcess {
public function publish(Publication $publication) {
// provedení jednotlivých úkonů
}
}
class EBook implements PublishingProcess {
public function publish(Publication $publication) {
// provedení jednotlivých úkonů
}
}
// GOOD
interface BookPublishingCommand
{
public function execute(Publication $publication);
}
class CommandManuscript implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Obdržen rukopis publikace z kategorie %s, %d stran.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class CommandTranslation implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Překlad publikace z kategorie %s, %d stran.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class CommandProofreading implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Jazyková korektura publikace " . "z kategorie %s, %d stran.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class CommandBookCover implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Příprava obálky pro publikaci " . "z kategorie %s, %d stran.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class CommandAssignISBN implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Přiřazení ISBN pro publikaci " . "z kategorie %s, %d stran.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class CommandPrint implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Tisk publikace z kategorie %s, %d stran.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class CommandPrintToPdf implements BookPublishingCommand
{
public function execute(Publication $publication)
{
printf(
"Tisk publikace z kategorie %s, " . "%d stran do PDF souboru.\n",
$publication->getCategory(),
$publication->getPageCount()
);
}
}
class Publisher
{
protected $processes = array();
public function addProcess($name, $commands)
{
$this->processes[$name] = $commands;
}
public function publish($process, Publication $publication)
{
if (!isset($this->processes[$process])) {
throw new BookPublishingException(
"Proces '" . $process . "' neexistuje."
);
}
printf("Zahájen proces: %s.\n", $process);
foreach ($this->processes[$process] as $command) {
$command->execute($publication);
}
}
}
// USAGE
$printedBookProcess = array(
new CommandManuscript(),
new CommandProofreading(),
new CommandBookCover(),
new CommandAssignISBN(),
new CommandPrint()
);
$eBookProcess = array(
new CommandTranslation(),
new CommandProofreading(),
new CommandBookCover(),
new CommandPrintToPdf()
);
$publisher = new Publisher();
$publisher->addProcess('printedBook', $printedBookProcess);
$publisher->addProcess('eBook', $eBookProcess);
$book1 = new Book('PC', 450);
$book2 = new Journal('MEDICINA', 50);
$publisher->publish('printedBook', $book1);
$publisher->publish('eBook', $book2);
<?php
/*
Návrhový vzor Template Method definuje rozhraní algoritmu v metodě a přenechává
implementaci jednotlivých kroků potomkům třídy. Ti mohou jednotlivé části
algoritmu modifikovat, aniž by změnili jeho strukturu.
*/
abstract class AbstractPrinter implements Printer, Observable
{
// ... atributy a metody původní třídy LaserPrinter
protected $paperAmount = 150;
abstract protected function replaceCartridges();
abstract protected function checkPrintingParts();
abstract protected function isLowPaperAmount();
protected function addPaper()
{
printf(
"Doplnění %d listů do zásobníku papíru.\n",
1000 - $this->paperAmount
);
$this->paperAmount = 1000;
}
final public function check()
{
printf("Probíhá kontola tiskárny %s:\n", $this->type);
$this->replaceCartridges();
$this->checkPrintingParts();
if ($this->isLowPaperAmount()) {
$this->addPaper();
} else {
print "Dostatečné množství papíru.\n";
}
}
}
class LaserPrinter extends AbstractPrinter
{
protected function replaceCartridges()
{
print "Výměna toneru typu AAA-111.\n";
}
protected function checkPrintingParts()
{
print "Kontrola fotoválce.\n";
}
protected function isLowPaperAmount()
{
if ($this->paperAmount < 200) {
return true;
}
return false;
}
}
class InkjetPrinter extends AbstractPrinter
{
protected function replaceCartridges()
{
print "Výměna inkoustových náplní typu BBB-222.\n";
}
protected function checkPrintingParts()
{
print "Kontrola trysek.\n";
}
protected function isLowPaperAmount()
{
if ($this->paperAmount < 100) {
return true;
}
return false;
}
}
$laserPrinter = new LaserPrinter('LP-1');
$inkjetPrinter = new InkjetPrinter('IP-1');
$laserPrinter->check();
$inkjetPrinter->check();
<?php
/*
Definice
---------
Návrhový vzor Mediator odstraňuje vzájemné vazby mezi komunikujícími objekty
a tím zajišťuje možnost vzájemné komunikace mezi objekty, které nejsou v přímé
interakci. Zavedením návrhového vzoru Mediator se mění vazby mezi objekty
z typu m:n na 1:n.
Pro implementaci tohoto návrhového vzoru jsou nezbytné následující kroky:
1. Definovat rozhraní prostředníka.
2. Definovat rozhraní objektů, které budou ke komunikaci využívat objekt
definovaný v bodě 1. Toto rozhraní musí obsahovat metodu, kterou bude
volat konkrétní prostředník.
3. Implementovat konkrétního prostředníka a v něm požadovanou logiku
zabezpečující komunikaci mezi objekty. V případě, že by byla požadovaná
logika velmi komplexní, definovat pomocné třídy prostředníka.
4. Implementovat konkrétního uživatele.
Návrhový vzor Mediator je konkurenčním návrhovým vzorem
k vzoru Observer, probíranému v předchozí kapitole, avšak oproti němu nedisponuje
možnostmi dynamického přidávání a odebírání objektů zajímajících se
o změny.
*/
interface Mediator
{
public function send($message, AbstractEmployee $employee);
}
abstract class AbstractEmployee
{
protected $id;
protected $mediator;
public function __construct($id, Mediator $mediator)
{
$this->setId($id);
$this->setMediator($mediator);
}
public function setId($id)
{
$this->id = $id;
}
public function getId()
{
return $this->id;
}
public function setMediator(Mediator $mediator)
{
$this->mediator = $mediator;
}
public function getMediator()
{
return $this->mediator;
}
public function send($message)
{
$this->mediator->send($message, $this);
}
abstract public function receive($message);
}
class NewsMediator implements Mediator
{
protected $employees = array();
public function registerEmployee(AbstractEmployee $employee)
{
$this->employees[] = $employee;
}
public function send($message, AbstractEmployee $sender)
{
foreach ($this->employees as $employee) {
if ($employee !== $sender) {
$employee->receive($message);
}
}
}
}
class Employee extends AbstractEmployee
{
public function receive($message)
{
printf("<%s> Přijatá zpráva: %s\n", $this->getId(), $message);
}
}
$mediator = new NewsMediator();
$employee1 = new Employee('EMP1', $mediator);
$employee2 = new Employee('EMP2', $mediator);
$employee3 = new Employee('EMP3', $mediator);
$employee4 = new Employee('EMP4', $mediator);
$mediator->registerEmployee($employee1);
$mediator->registerEmployee($employee2);
$mediator->registerEmployee($employee3);
$mediator->registerEmployee($employee4);
$employee3->send('Zpráva od EMP3');
$employee1->send('Odpověď od EMP1');
<?php
/*
Návrhový vzor Flyweight zabezpečuje společné využívání velmi podobných objektů,
aby je bylo možné použít ve velkém počtu bez nárůstu spotřeby paměti.
Při implementaci návrhového vzoru Flyweight to neznamená, že příslušné třídy
nesmějí obsahovat žádný atribut, který by uchovával jejich stav. Při implementaci
se rozlišuje mezi vnitřním (nebo též vlastní – angl. intrinsic) a vnějším (nebo též
nevlastní – angl. extrinsic) stavem. Vnitřní stav návrhový vzor i nadále uchovává
a obsahuje výlučně informace, které jsou nezávislé na obsahu. Vnější stav je závislý
na obsahu, a proto jej nelze uchovávat a společně využívat ve třídách návrhového
vzoru Flyweight.
Definice
----------
Návrhový vzor Flyweight zabezpečuje společné využívání velmi podobných objektů,
aby je bylo možné použít ve velkém počtu bez nárůstu spotřeby paměti.
Pro implementaci návrhového vzoru Flyweight jsou nutné následující kroky:
1. Identifikovat třídu, z níž se vytváří velké množství instancí.
2. Tuto třídu osvobodit od co největšího počtu objektů, které uchovávají stav
konkrétní implementace. Tento stav instancí uložit někde mimo instance.
3. Implementovat třídu, která slouží jako zástupce „mušího“ objektu.
*/
// optimalizace pro Muší vahu :), kod z Factory kap. 3
// OLD
abstract class Cell
{
protected $content = null;
public function __construct($content)
{
$this->content = $content;
}
abstract public function show();
}
// NEW
abstract class Cell
{
abstract public function show($data);
}
// OLD
class TextCell extends Cell
{
public function show()
{
$diff = strlen($this->content) - mb_strlen($this->content, 'UTF-8');
print '|' . str_pad($this->content, 15 + $diff);
}
}
// NEW
class TextCell extends Cell
{
public function show($data)
{
$diff = strlen($data) - mb_strlen($data, 'UTF-8');
print '|' . str_pad($data, 15 + $diff);
}
}
// OLD
interface TableFactory
{
public function createCell($content);
public function createRow();
public function createHeader();
public function createTable();
}
// NEW
interface TableFactory
{
public function createCell();
public function createRow();
public function createHeader();
public function createTable();
}
// OLD
abstract class Row
{
protected $cellData = array();
public function addCell($cell)
{
$this->cellData[] = $cell;
}
abstract public function show();
}
// NEW
abstract class Row
{
protected $cellData = array();
protected $flyWeightCell;
public function __construct(Cell $cell)
{
$this->flyWeightCell = $cell;
}
// ... ostatní metody třídy
}
// OLD
class TextRow extends Row
{
public function show()
{
foreach ($this->cells as $cell) {
$cell->show();
}
print "|\n";
$str = '';
for ($i = 0; $i < count($this->cells); $i++) {
$str .= '+' . str_repeat('-', 15);
}
print $str . "+\n";
}
}
// NEW
class TextRow extends Row
{
public function show()
{
foreach ($this->cellData as $data) {
$this->flyWeightCell->show($data);
}
print "|\n";
$str = '';
for ($i = 0; $i < count($this->cellData); $i++) {
$str .= '+' . str_repeat('-', 15);
}
print $str . "+\n";
}
}
// OLD
class TextHeader extends Header
{
public function show()
{
$str = '';
for ($i = 0; $i < count($this->cells); $i++)
{
$str .= '+' . str_repeat('-', 15);
}
print $str . "+\n";
foreach ($this->cells as $cell)
{
$cell->show();
}
print "|\n";
print $str . "+\n";
}
}
// NEW
class TextHeader extends Header
{
public function show()
{
$str = '';
for ($i = 0; $i < count($this->cellData); $i++)
{
$str .= '+' . str_repeat('-',15);
}
print $str . "+\n";
foreach ($this->cellData as $data)
{
$this->flyWeightCell->show($data);
}
print "|\n";
print $str . "+\n";
}
}
// OLD
class TextTableFactory implements TableFactory
{
public function createCell($content)
{
return new TextCell($content);
}
public function createRow()
{
return new TextRow();
}
public function createHeader()
{
return new TextHeader();
}
public function createTable()
{
return new TextTable();
}
}
// NEW
class TextTableFactory implements TableFactory
{
private $cell = null;
public function createCell()
{
if (null === $this->cell) {
$this->cell = new TextCell();
}
return $this->cell;
}
public function createRow()
{
$row = new TextRow($this->createCell());
return $row;
}
public function createHeader()
{
$header = new TextHeader($this->createCell());
return $header;
}
public function createTable()
{
return new TextTable();
}
}
// OLD
class PublicationList
{
protected $tableFactory = null;
public function __construct(TableFactory $tf)
{
$this->tableFactory = $tf;
}
public function displayTable($data)
{
$table = $this->tableFactory->createTable();
$header = $this->tableFactory->createHeader();
$header->addCell($this->tableFactory->createCell('Kategorie'));
$header->addCell($this->tableFactory->createCell('Počet stran'));
$table->setHeader($header);
foreach ($data as $line) {
$row = $this->tableFactory->createRow();
foreach ($line as $field) {
$cell = $this->tableFactory->createCell($field);
$row->addCell($cell);
}
$table->addRow($row);
}
$table->show();
}
}
// NEW
class PublicationList
{
protected $tableFactory = null;
public function __construct(TableFactory $tf)
{
$this->tableFactory = $tf;
}
public function displayTable($data)
{
$table = $this->tableFactory->createTable();
$header = $this->tableFactory->createHeader();
$header->addCell('Kategorie');
$header->addCell('Počet stran');
$table->setHeader($header);
foreach ($data as $line) {
$row = $this->tableFactory->createRow();
$table->addRow($row);
foreach ($line as $field) {
$row->addCell($field);
}
}
$table->show();
}
}
// USAGE, stale stejne jen se zmenil pocet objektů
/*
Tam, kde se v původní implementaci používaly rozdílné instance třídy cz\k1886\
tables\text\TextCell, jsou nyní všude odkazy na stejnou instanci.
Tuto skutečnost můžete vidět na čísle za instancí. V tomto případě je to #5. Místo osmi
instancí této třídy tedy potřebujete už jen jednu, čímž jste zredukovali počet
potřebných instancí o 87,5 %.
Je samozřejmé, že můžete v redukování objektů pokračovat i dále a použít muší
váhu i na objekty řádků tabulky
*/
$publications = array(
array('PC', 100),
array('PC', 380),
array('medicína', 250),
array('historie', 70),
);
$pl = new PublicationList(new TextTableFactory());
$pl->displayTable($publications);