Адаптер (шаблон проектирования) — КиберПедия 

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Адаптер (шаблон проектирования)

2019-08-07 142
Адаптер (шаблон проектирования) 0.00 из 5.00 0 оценок
Заказать работу

Адаптер, Adapter — структурный шаблон проектирования, предназначенный для организации использования функций объекта, недоступного для модификации, через специально созданный интерфейс.

Основные характеристики

Задача

Система поддерживает требуемые данные и поведение, но имеет неподходящий интерфейс. Чаще всего шаблон Адаптер применяется если необходимо создать класс, производный от вновь определяемого или уже существующего абстрактного класса.

Способ решения

Адаптер предусматривает создание класса-оболочки[1] с требуемым интерфейсом.

Участники

Класс Adapter приводит интерфейс класса Adaptee в соответствие с интерфейсом класса Target (наследником которого является Adapter). Это позволяет объекту Client использовать объект Adaptee так, словно он является экземпляром класса Target.

Следствия

Шаблон Адаптер позволяет включать уже существующие объекты в новые объектные структуры, независимо от различий в их интерфейсах.

Реализация

Включение уже существующего класса в другой класс. Интерфейс включающего класса приводится в соответствие с новыми требованиями, а вызовы его методов преобразуются в вызовы методов включённого класса.

Замечания и комментарии

Шаблон Адаптер позволяет в процессе проектирования не принимать во внимание возможные различия в интерфейсах уже существующих классов. Если есть класс, обладающий требуемыми методами и свойствами (по крайней мере, концептуально), то при необходимости всегда можно воспользоваться шаблоном Адаптер для приведения его интерфейса к нужному виду.

Близким Адаптеру является шаблон Фасад, не всегда можно отличить один от другого[2].

Применение шаблона

Типичным примером использования шаблона Адаптер можно назвать создание классов, приводящих к единому интерфейсу функции языка PHP обеспечивающие доступ к различным СУБД[3].

Вариант решения данной проблемы с использованием шаблона Адаптер показан на рисунке.

Пример использования шаблона Адаптер

 

Примеры реализации [показать]

Пример реализации шаблона на 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()");

}

}

 }

Примечания

  1. Близость значений терминов оболочка и обёртка (англ. wrapper — используется как синоним декоратора) иногда приводит к путанице и Адаптер определяют как синоним шаблона Декоратор, в то время как это два разных шаблона и последний решает иную задачу, а именно: подключение дополнительных обязательств к объекту.
  2. Разница состоит в том, что шаблон Фасад предназначен для упрощения интерфейса, тогда как шаблон Адаптер предназначен для приведения различных существующих интерфейсов к единому требуемому виду.
  3. В языке PHP доступ к СУБД реализован в виде набора функций, для каждой СУБД они имеют различные наименования и, иногда, различный набор используемых параметров, что приводит к значительным проблемам при переходе с одной СУБД на другую, если такой переход заранее не обеспечен использованием шаблона Адаптер.

Мост (шаблон проектирования)

Bridge, Мост — шаблон проектирования, используемый в проектировании программного обеспечения чтобы «разделять абстракцию и реализацию так, чтобы они могли изменяться независимо». Шаблон bridge (от англ. — мост) использует инкапсуляцию, агрегирование и может использовать наследование для того, чтобы разделить ответственность между классами.

Цель

При частом изменении класса, преимущества объектно-ориентированного подхода становятся очень полезными, позволяя делать изменения в программе, обладая минимальными сведениями о реализации программы. Шаблон bridge является полезным там, где не только сам класс часто меняется, но и то, что класс делает.

Описание

Когда абстракция и реализация разделены, они могут изменяться независимо. Рассмотрим такую абстракцию как фигура. Существует множество типов фигур, каждая со своими свойствами и методами. Однако есть что-то, что объединяет все фигуры. Например, каждая фигура должна уметь рисовать себя, масштабироваться и т. п. В то же время рисование графики может отличаться в зависимости от типа ОС, или графической библиотеки. Фигуры должны иметь возможность рисовать себя в различных графических средах, но реализовывать в каждой фигуре все способы рисования или модифицировать фигуру каждый раз при изменении способа рисования непрактично. В этом случае помогает шаблон bridge, позволяя создавать новые классы, которые будут реализовывать рисование в различных графических средах. При использовании такого подхода очень легко можно добавлять как новые фигуры, так и способы их рисования.

Примеры

Пример на C#

using System;

 

namespace Bridge

{

 

// MainApp test application

 

class MainApp

{

static void Main()

{

Abstraction ab = new RefinedAbstraction();

 

// Set implementation and call

ab.Implementor = new ConcreteImplementorA();

ab.Operation();

 

// Change implemention and call

ab.Implementor = new ConcreteImplementorB();

ab.Operation();

 

// Wait for user

Console.Read();

  }

}

 

/// <summary>

/// Abstraction - абстракция

/// </summary>

/// <remarks>

/// <li>

/// <lu>определяем интерфейс абстракции;</lu>

/// <lu>хранит ссылку на объект <see cref="Implementor"/></lu>

/// </li>

/// </remarks>

class Abstraction

{

protected Implementor implementor;

 

// Property

public Implementor Implementor

{

set{ implementor = value; }

}

 

public virtual void Operation()

{

implementor.Operation();

}

}

 

/// <summary>

/// Implementor - реализатор

/// </summary>

/// <remarks>

/// <li>

/// <lu>определяет интерфейс для классов реализации. Он не обязан точно

/// соотведствовать интерфейсу класса <see cref="Abstraction"/>. На самом деле оба

/// интерфейса могут быть совершенно различны. Обычно интерфейс класса

/// <see cref="Implementor"/> представляет только примитивные операции, а класс

/// <see cref="Abstraction"/> определяет операции более высокого уровня,

/// базирующиеся на этих примитивах;</lu>

/// </li>

/// </remarks>

abstract class Implementor

{

public abstract void Operation();

}

 

/// <summary>

/// RefinedAbstraction - уточненная абстракция

/// </summary>

/// <remarks>

/// <li>

/// <lu>расширяет интерфейс, определенный абстракцией <see cref="Abstraction"/></lu>

/// </li>

/// </remarks>

class RefinedAbstraction: Abstraction

{

public override void Operation()

{

implementor.Operation();

}

}

 

/// <summary>

/// ConcreteImplementor - конкретный реализатор

/// </summary>

/// <remarks>

/// <li>

/// <lu>содержит конкретную реализацию интерфейса <see cref="Implementor"/></lu>

/// </li>

/// </remarks>

class ConcreteImplementorA: Implementor

{

public override void Operation()

{

Console.WriteLine("ConcreteImplementorA Operation");

}

}

 

// "ConcreteImplementorB"

 

class ConcreteImplementorB: Implementor

{

public override void Operation()

{

Console.WriteLine("ConcreteImplementorB Operation");

}

  }

}

Пример JavaScript

// Implementor ("интерфейс")

function Implementor() {

   this.operation = function() {};

}

 

// ConcreteImplementor (реализация Implementor)

function ConcreteImplementorA() {

   this.operation = function() {

          alert("ConcreteImplementorA.operation");

   };

}

ConcreteImplementorA.prototype = new Implementor();

ConcreteImplementorA.prototype.constructor = ConcreteImplementorA;

 

function ConcreteImplementorB() {

   this.operation = function() {

          alert("ConcreteImplementorB.operation");

   };

}

ConcreteImplementorB.prototype = new Implementor();

ConcreteImplementorB.prototype.constructor = ConcreteImplementorB;

 

// Abstraction

function Abstraction() {

   var implementor;

 

   this.getImplementor = function() {

          // доступ к implementor'у из RefinedAbstraction

          return implementor;

   };

   this.setImplementor = function(val) {

          implementor = val;

   };

   this.operation = function() {

          implementor.operation();

   };

}

 

// RefinedAbstraction

function RefinedAbstraction() {

   var abstr = new Abstraction();

 

   this.setImplementor = function(val) {

          abstr.setImplementor(val);

   };

   this.operation = function() {

          abstr.operation();

   };

}

 

// использование:

var refAbstr = new RefinedAbstraction();

refAbstr.setImplementor(new ConcreteImplementorA());

refAbstr.operation(); // "ConcreteImplementorA.operation"

 

refAbstr.setImplementor(new ConcreteImplementorB());

refAbstr.operation(); // "ConcreteImplementorB.operation"

Без необходимости перегрузки методов Abstraction, можно значительно упростить RefinedAbstraction:

function RefinedAbstraction() {

   Abstraction.call(this);

}

Так же можно сохранить ссылки на перегружаемые методы сразу после инстанцирования Abstraction:

function RefinedAbstraction() {

   Abstraction.call(this);

   var abstr_setImplementor = this.setImplementor;

 

   this.setImplementor = function(val) {

          abstr_setImplementor(val);

   };

}

 


Поделиться с друзьями:

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Семя – орган полового размножения и расселения растений: наружи у семян имеется плотный покров – кожура...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.052 с.