Шаблоны проектирования: Адаптер
https://ruseller.com/lessons.php?rub=37&id=2173
В прошлом уроке мы рассмотрели возможность шаблона проектирования Фасад, с помощью которого можно перестроить код крупного проекта.
В этой статье под наш прицел попал шаблон проектирования под названием Адаптер. Его использование целесообразно, если в вашем проекте происходит взаимодействие с сторонними API, или другим классом, который подвержен частым изменениям. Данный шаблон относится к “структурному” типу т.к. с его помощью мы можем мы можем организовать структуру классов по определённому образцу.
Ещё раз хотел бы напомнить, что шаблоны проектирования ничем не отличаются от обычных классов. С их помощью мы можем лучшим способом структурировать наши классы, управлять их поведением.
Задача
03 |
public function __construct() { |
07 |
public function send( $msg ) { |
13 |
$twitter = new Twitter(); |
14 |
$twitter ->send( 'Posting on Twitter' ); |
В приведённом примере мы используем класс Twitter для упрощения процедуры публикации сообщения. Далее мы создаём объект для обращения к Twitter API и публикации сообщения. Представьте, что данный код используется в нескольких местах. Обратите внимание, что для публикации сообщения мы используем метод $twitter->send('Posting on Twitter');
Некоторое время назад, Twitter изменили название метода API для публикации сообщения. Те, кто пользовался предыдущей версией явно увидят сложившуюся проблему. Нам необходимо поменять все названия методов для отправки твитта. Представьте сколько кода нам нужно поменять и сколько на это потребуется времени. Что если смена названия произойдёт ещё раз?
Решение
В качестве решения можем применить шаблон проектирования Адаптер.
Согласно Wikipedia:
Адаптер — структурный шаблон проектирования, предназначенный для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.
Таким образом, в первую очередь, нам необходимо создать интерфейс. Изменение кода сторонней библиотеки не имеет никакого смысла, т.к. её содержание может в любой момент измениться.
Давайте рассмотрим код, написанный на основе шаблона проектирования Адаптер:
04 |
public function __construct() { |
08 |
public function send( $msg ) { |
15 |
interface socialAdapter { |
16 |
public function send( $msg ); |
19 |
class twitterAdapter implements socialAdapter { |
23 |
public function __construct(Twitter $twitter ) { |
24 |
$this ->twitter = $twitter ; |
27 |
public function send( $msg ) { |
28 |
$this ->twitter->send( $msg ); |
Изучив код вы поймёте, что мы не тронули исходный класс Twitter. Вместо этого мы создали интерфейс нашего социального адаптера для класса Twitter.
Далее вместо создания объекта типа Twitter, мы создали объект его адаптера. В качестве параметра передаём объект основного класса Twitter, для того, чтобы наш адаптер имел доступ к объекту основного класса.
Теперь давайте определим как использовать методы исходного класса:
2 |
$twitter = new twitterAdapter( new Twitter()); |
3 |
$twitter ->send( 'Posting to Twitter' ); |
Теперь представьте, что Twitter изменил название метода с send на sendTweet. В этом случае, нам нужно изменить только twitterAdapter. Взгляните на изменённый код адаптера.
01 |
class twitterAdapter implements socialAdapter { |
05 |
public function __construct(Twitter $twitter ) { |
06 |
$this ->twitter = $twitter ; |
09 |
public function send( $msg ) { |
10 |
$this ->twitter->sendTweet( $msg ); |
Только одно изменение и мы снова в теме.
Добавление нового адаптера
Давайте рассмотрим как можно использовать шаблон проектирования Адаптер в других случаях. Теперь очень просто добавить новый класс на основе существующего адаптера. Допустим Facebook API позволяет обновить статус.
Вместо того чтобы напрямую использовать класс Facebook, создадим новый адаптер.
03 |
public function __construct() { |
07 |
public function updateStatus( $msg ) { |
14 |
class facebookAdapter implements socialAdapter { |
18 |
public function __construct(Facebook $facebook ) { |
19 |
$this ->facebook = $facebook ; |
22 |
public function send( $msg ) { |
23 |
$this ->facebook->updateStatus( $msg ); |
29 |
$facebook = new facebookAdapter( new Facebook()); |
30 |
$facebook ->send( 'Posting to Facebook' ); |
Как видите, принцип тот же. Вы определяете класс оболочку, в который передаёте оригинальный объект класса. При изменении API, вам нужно сменить код только в одном месте.
Заключение
Крупные приложения несомненно включат в себя работу с сторонними API, так что использование шаблона проектирования Адаптер целесообразно, если вы хотите избежать рассмотренной нами проблемы.
Я сделал всё зависящее от меня, чтобы продемонстрировать элементарный и одновременно полезный пример использования шаблона проектирования Адаптер.