Адаптер (шаблон проектирования)
| Адаптер | |
| Adapter | |
| Тип: |
структурный |
|---|---|
| Назначение: |
для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс (приводит интерфейс класса (или нескольких классов) к интерфейсу требуемого вида) |
| Применяется в случаях: |
система поддерживает требуемые данные и поведение, но имеет неподходящий интерфейс. Чаще всего шаблон Адаптер применяется если необходимо создать класс, производный от вновь определяемого или уже существующего абстрактного класса. |
| Плюсы: |
|
| Родственные шаблоны: | |
| Описан в Design Patterns |
Да |
Адаптер, Adapter или Wrapper/Обёртка — структурный шаблон проектирования, предназначенный для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.
Содержание |
[править] Основные характеристики
[править] Задача
Система поддерживает требуемые данные и поведение, но имеет неподходящий интерфейс. Чаще всего шаблон Адаптер применяется, если необходимо создать класс, производный от вновь определяемого или уже существующего абстрактного класса.
[править] Способ решения
Адаптер предусматривает создание класса-оболочки[1] с требуемым интерфейсом.
[править] Участники
Класс Adapter приводит интерфейс класса Adaptee в соответствие с интерфейсом класса Target (наследником которого является Adapter). Это позволяет объекту Client использовать объект Adaptee (посредством адаптера Adapter) так, словно он является экземпляром класса Target.
Таким образом Client обращается к интерфейсу Target, реализованному в наследнике Adapter, который перенаправляет обращение к Adaptee.
[править] Следствия
Шаблон Адаптер позволяет включать уже существующие объекты в новые объектные структуры, независимо от различий в их интерфейсах.
[править] Реализация
Включение уже существующего класса в другой класс. Интерфейс включающего класса приводится в соответствие с новыми требованиями, а вызовы его методов преобразуются в вызовы методов включённого класса.
[править] Пример на Java (class adapter)
// Target public interface Chief { public Object makeBreakfast(); public Object makeLunch(); public Object makeDinner(); } // Adaptee public class Plumber { public Object getScrewNut() { ... } public Object getPipe() { ... } public Object getGasket() { ... } } // Adapter public class ChiefAdapter extends Plumber implements Chief { public Object makeBreakfast() { return getGasket(); } public Object makeLunch() { return getPipe(); } public Object makeDinner() { return getScrewNut(); } } // Client public class Client { public static void eat(Object dish) { ... } public static void main(String[] args) { Chief ch = new ChiefAdapter(); Object dish = ch.makeBreakfast(); eat(dish); dish = ch.makeLunch(); eat(dish); dish = ch.makeDinner(); eat(dish); callAmbulance(); } }
[править] Пример на Java (object adapter)
package com.designpatterns.objectadapter; /* Файл Chief.java * * */ public interface Chief { public Object makeBreakfast(); public Object makeDinner(); public Object makeSupper(); } package com.designpatterns.objectadapter; /* Файл Plumber.java * * */ public class Plumber { public Object getPipe(){ return new Object(); } public Object getKey(){ return new Object(); } public Object getScrewDriver(){ return new Object(); } } package com.designpatterns.objectadapter; /* Файл ChiefAdapter.java * * */ public class ChiefAdapter implements Chief{ private Plumber plumber = new Plumber(); @Override public Object makeBreakfast() { return plumber.getKey(); } @Override public Object makeDinner() { return plumber.getScrewDriver(); } @Override public Object makeSupper() { return plumber.getPipe(); } } package com.designpatterns.objectadapter; /* Файл Client.java * * */ public class Client { public static void main (String [] args){ Chief chief = new ChiefAdapter(); Object key = chief.makeDinner(); } }
[править] Пример реализации на PHP5
class Search { private $text; private $word; function __construct($text,$word) { $this->text = $text; $this->word = $word; } function searchWordInText() { return $this->text; } function getWord() { return $this->word; } } class SearchAdapter { private $aSearch; function __construct(Search $aSearch) { $this->aSearch = $aSearch; } function searchWordInText() { return 'Эти слова '.$this->aSearch->getWord().' найдены в тексте '.$this->aSearch->searchWordInText(); } } $search = new Search("текст", "слова"); $searchAdapter = new SearchAdapter($search); echo $searchAdapter->searchWordInText();
[править] Пример на Python
class GameConsole: def create_game_picture(self): return 'picture from console' class Antenna: def create_wave_picture(self): return 'picture from wave' class SourceGameConsole(GameConsole): def get_picture(self): return self.create_game_picture() class SourceAntenna(Antenna): def get_picture(self): return self.create_wave_picture() class TV: def __init__(self, source): self.source = source def show_picture(self): return self.source.get_picture() g = SourceGameConsole() a = SourceAntenna() game_tv = TV(g) cabel_tv = TV(a) print game_tv.show_picture() print cabel_tv.show_picture()
[править] Пример на C#
using System; namespace Adapter { class MainApp { static void Main() { // Create adapter and place a request Target target = new Adapter(); target.Request(); // Wait for user Console.Read(); } } // "Target" class Target { public virtual void Request() { Console.WriteLine("Called Target Request()"); } } // "Adapter" class Adapter : Target { private Adaptee adaptee = new Adaptee(); public override void Request() { // Possibly do some other work // and then call SpecificRequest adaptee.SpecificRequest(); } } // "Adaptee" class Adaptee { public void SpecificRequest() { Console.WriteLine("Called SpecificRequest()"); } } }
[править] Замечания и комментарии
Шаблон Адаптер позволяет в процессе проектирования не принимать во внимание возможные различия в интерфейсах уже существующих классов. Если есть класс, обладающий требуемыми методами и свойствами (по крайней мере, концептуально), то при необходимости всегда можно воспользоваться шаблоном Адаптер для приведения его интерфейса к нужному виду.
Близким Адаптеру является шаблон Фасад, не всегда можно отличить один от другого[2].
[править] Применение шаблона
Типичным примером использования шаблона Адаптер можно назвать создание классов, приводящих к единому интерфейсу функции языка PHP обеспечивающие доступ к различным СУБД[3].
Вариант решения данной проблемы с использованием шаблона Адаптер показан на рисунке.
[править] Примечания
- ↑ Близость значений терминов оболочка и обёртка (англ. wrapper — используется как синоним декоратора) иногда приводит к путанице и Адаптер определяют как синоним шаблона Декоратор, в то время как это два разных шаблона и последний решает иную задачу, а именно: подключение дополнительных обязательств к объекту.
- ↑ Разница состоит в том, что шаблон Фасад предназначен для упрощения интерфейса, тогда как шаблон Адаптер предназначен для приведения различных существующих интерфейсов к единому требуемому виду.
- ↑ В языке PHP доступ к СУБД реализован в виде набора функций, для каждой СУБД они имеют различные наименования и, иногда, различный набор используемых параметров, что приводит к значительным проблемам при переходе с одной СУБД на другую, если такой переход заранее не обеспечен использованием шаблона Адаптер.
[править] Литература
- Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М.: «Вильямс», 2002. — С. 288. — ISBN 0-201-71594-5
- Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес Приемы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб: «Питер», 2007. — С. 366. — ISBN 978-5-469-01136-1 (также ISBN 5-272-00355-1)
[править] Ссылки
- Паттерн проектирования «Адаптер» на Хабрахабре
- Паттерн Adapter (Адаптер) — назначение, описание, реализация на С++, достоинства и недостатки
