Оглавление:
Карта сайта:
Оглавление:
Карта сайта:
Это старая версия документа!
Шаблон адаптера позволяет обернуть несовместимый объект в адаптер, чтобы сделать его совместимым с другим классом.
Чаще всего «Адаптер» применяется, если необходимо создать определенный класс, производный от уже существующего.
Привести нестандартный или неудобный интерфейс какого-то класса в интерфейс, совместимый с вашим кодом. Адаптер
позволяет классам работать вместе стандартным образом, что обычно не получается из-за несовместимых интерфейсов,
предоставляя для этого прослойку с интерфейсом, удобным для клиентов, самостоятельно используя оригинальный интерфейс.
Использование:
причём расширить суперкласс вы не можете.
Преимущества:
Недостатки:
Связи с другими паттернами
постфактум, чтобы заставить несовместимые классы работать вместе.
Декоратор поддерживает рекурсивную вложенность, чего не скажешь об Адаптере.
предоставляет тот же интерфейс.
Фасад оборачивает целую подсистему. Кроме того, Адаптер позволяет двум существующим интерфейсам работать сообща,
вместо того, чтобы задать полностью новый.
«композиции», то есть делегирования работы другим объектам. Тем не менее, они отличаются тем, что решают разные
проблемы. Помните, что паттерны – это не только рецепт построения кода определённым образом, но и описание проблем,
которые привели к данному решению.
Adapter.php
<?php interface NativeWorker { public function countSalary(): int; } interface OutsourceWorker { public function countSalaryByHour($hours): int; } class NativeDeveloper implements NativeWorker { public function countSalary(): int { return 3000 * 20; } } class OutsourceDeveloper implements OutsourceWorker { public function countSalaryByHour($hours): int { return $hours * 300; } } class OutsourceWorkerAdapter implements NativeWorker { private OutsourceWorker $outsourceWorker; public function __construct(OutsourceWorker $outsourceWorker) { $this->outsourceWorker = $outsourceWorker; } public function countSalary(): int { return $this->outsourceWorker->countSalaryByHour(40); } } $nativeDeveloper = new NativeDeveloper(); echo $nativeDeveloper->countSalary(); // 60000 $outsourceDeveloper = new OutsourceDeveloper(); echo $outsourceDeveloper->countSalaryByHour(40); //12000 $outsourceWorkerAdapter = new OutsourceWorkerAdapter($outsourceDeveloper); echo $outsourceWorkerAdapter->countSalary(); // 12000 // ----------- 2 ----------- interface Book { public function turnPage(); public function open(); public function getPage(): int; } class PaperBook implements Book { private int $page; public function open(): void { $this->page = 1; } public function turnPage(): void { $this->page++; } public function getPage(): int { return $this->page; } } interface EBook { public function unlock(); public function pressNext(); /** * возвращает текущую страницу и общее количество страниц, например [10, 100] - страница 10 из 100 * * @return int[] */ public function getPage(): array; } /** * Вот этот адаптер. Обратите внимание, что в нем реализована книга, * таким образом, вам не нужно изменять код клиента, который использует книгу */ class EBookAdapter implements Book { public function __construct(protected EBook $eBook) { } /** * Этот класс выполняет надлежащий перевод с одного интерфейса на другой. */ public function open() { $this->eBook->unlock(); } public function turnPage() { $this->eBook->pressNext(); } /** * обратите внимание на адаптированное поведение здесь: eBook::getPage() вернет два целых числа, но Book * поддерживает только средство получения текущей страницы, поэтому мы адаптируем поведение здесь */ public function getPage(): int { return $this->eBook->getPage()[0]; } } /** * это адаптированный класс. В производственном коде это может быть класс из другого пакета, какой-нибудь код поставщика. * Обратите внимание, что он использует другую схему именования, и реализация делает нечто подобное, но другим способом */ class Kindle implements EBook { private int $page = 1; private int $totalPages = 100; public function pressNext() { $this->page++; } public function unlock() { } /** * возвращает текущую страницу и общее количество страниц, например [10, 100] - страница 10 из 100 * * @return int[] */ public function getPage(): array { return [$this->page, $this->totalPages]; } } $book = new PaperBook(); $book->open(); $book->turnPage(); echo $book->getPage(); // 2 $kindle = new Kindle(); $kindle->unlock(); $kindle->pressNext(); print_r($kindle->getPage()); // [0] => 2 // [1] => 100 $kindle2 = new Kindle(); $book2 = new EBookAdapter($kindle2); $book2->open(); $book2->turnPage(); $book2->turnPage(); echo $book2->getPage(); // 3