адаптер-любой реальный пример шаблона адаптера



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



можете ли вы поделиться каким-либо примером шаблона адаптера?



p. s.Я попытался найти существующие вопросы на stackoverflow, но не нашел ответа, поэтому разместил его как новый вопрос. Если вы знайте, что уже есть ответ на это, а затем, пожалуйста, перенаправьте.

1053   12  

12 ответов:

многие примеры адаптера тривиальны или нереалистичны (прямоугольник против LegacyRectangle, храповик против сокета,SquarePeg против RoundPeg,утка против индейки). Хуже того, многие не показывают несколько адаптеров для различных адаптеров (кто-то процитировал массивы Java.asList в качестве примера шаблона адаптера). Адаптация интерфейса только один класс работать с другим кажется слабым примером адаптера GoF узор. Этот шаблон использует наследование и полиморфизм, поэтому можно было бы ожидать, что хороший пример покажет несколько реализаций адаптеров для различных адаптеров.

на лучший пример я нашел это в главе 26 из применение UML и шаблонов: введение в объектно-ориентированный анализ и проектирование и итеративную разработку (3-е издание). Следующие изображения взяты из инструкторского материала, предоставленного на FTP-сайте для книги.

первый показывает, как приложение может использовать несколько реализаций (адаптеров), которые функционально похожи (например, налоговые калькуляторы, бухгалтерские модули, услуги авторизации кредитов и т. д.) но есть разные API. Мы хотим избежать жесткого кодирования нашего кода доменного уровня для обработки различных возможных способов расчета налогов, пост-продаж, авторизации запросов кредитных карт и т. д. Это все внешние модули, которые могут отличаться и для которых мы не можем изменить код. Адаптер позволяет нам выполнять жесткое кодирование в адаптере, тогда как наш код доменного уровня всегда использует один и тот же интерфейс (интерфейс IWhateverAdapter).

Fig. 26.1

мы не видим на приведенном выше рисунке реальных адаптеров. Однако, на следующем рисунке показано, как полиморфный вызов postSale(...) в интерфейсе IAccountingAdapter производится, что приводит к проводке продажи через SOAP в систему SAP.

Fig. 26.2

преобразование интерфейса в другой интерфейс.

любой реальный пример шаблона адаптера

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

enter image description here

Как превратить француза в нормального человека...

 public interface IPerson
    {
        string Name { get; set; }
    }

    public interface IFrenchPerson
    {
        string Nom { get; set; }
    }

    public class Person : IPerson
    {
        public string Name { get; set; }
    }

    public class FrenchPerson : IFrenchPerson
    {
        public string Nom { get; set; }
    }

    public class PersonService
    {
        public void PrintName(IPerson person)
        {
            Debug.Write(person.Name);
        }
    }

    public class FrenchPersonAdapter : IPerson
    {
        private readonly IFrenchPerson frenchPerson;

        public FrenchPersonAdapter(IFrenchPerson frenchPerson)
        {
            this.frenchPerson = frenchPerson;
        }

        public string Name 
        {
            get { return frenchPerson.Nom; }
            set { frenchPerson.Nom = value; }
        }
    } 

пример

    var service = new PersonService();
    var person = new Person();
    var frenchPerson = new FrenchPerson();

    service.PrintName(person);
    service.PrintName(new FrenchPersonAdapter(frenchPerson));

вот пример, который имитирует преобразования analog data до digit data.

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


код

аналоговый сигнал.java

package eric.designpattern.adapter;

public interface AnalogSignal {
    float[] getAnalog();

    void setAnalog(float[] analogData);

    void printAnalog();
}

DigitSignal.java

package eric.designpattern.adapter;

public interface DigitSignal {
    byte[] getDigit();

    void setDigit(byte[] digitData);

    void printDigit();
}

FloatAnalogSignal.java

package eric.designpattern.adapter;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FloatAnalogSignal implements AnalogSignal {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private float[] data;

    public FloatAnalogSignal(float[] data) {
        this.data = data;
    }

    @Override
    public float[] getAnalog() {
        return data;
    }

    @Override
    public void setAnalog(float[] analogData) {
        this.data = analogData;
    }

    @Override
    public void printAnalog() {
        logger.info("{}", Arrays.toString(getAnalog()));
    }
}

BinDigitSignal.java

package eric.designpattern.adapter;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BinDigitSignal implements DigitSignal {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private byte[] data;

    public BinDigitSignal(byte[] data) {
        this.data = data;
    }

    @Override
    public byte[] getDigit() {
        return data;
    }

    @Override
    public void setDigit(byte[] digitData) {
        this.data = digitData;
    }

    @Override
    public void printDigit() {
        logger.info("{}", Arrays.toString(getDigit()));
    }
}

AnalogToDigitAdapter.java

package eric.designpattern.adapter;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * Adapter - convert analog data to digit data.
 * </p>
 * 
 * @author eric
 * @date Mar 8, 2016 1:07:00 PM
 */
public class AnalogToDigitAdapter implements DigitSignal {
    public static final float DEFAULT_THRESHOLD_FLOAT_TO_BIN = 1.0f; // default threshold,
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private AnalogSignal analogSignal;
    private byte[] digitData;
    private float threshold;
    private boolean cached;

    public AnalogToDigitAdapter(AnalogSignal analogSignal) {
        this(analogSignal, DEFAULT_THRESHOLD_FLOAT_TO_BIN);
    }

    public AnalogToDigitAdapter(AnalogSignal analogSignal, float threshold) {
        this.analogSignal = analogSignal;
        this.threshold = threshold;
        this.cached = false;
    }

    @Override
    public synchronized byte[] getDigit() {
        if (!cached) {
            float[] analogData = analogSignal.getAnalog();
            int len = analogData.length;
            digitData = new byte[len];

            for (int i = 0; i < len; i++) {
                digitData[i] = floatToByte(analogData[i]);
            }
        }

        return digitData;
    }

    // not supported, should set the inner analog data instead,
    @Override
    public void setDigit(byte[] digitData) {
        throw new UnsupportedOperationException();
    }

    public synchronized void setAnalogData(float[] analogData) {
        invalidCache();
        this.analogSignal.setAnalog(analogData);
    }

    public synchronized void invalidCache() {
        cached = false;
        digitData = null;
    }

    @Override
    public void printDigit() {
        logger.info("{}", Arrays.toString(getDigit()));
    }

    // float -> byte convert,
    private byte floatToByte(float f) {
        return (byte) (f >= threshold ? 1 : 0);
    }
}

Код - Тест дело

AdapterTest.java

package eric.designpattern.adapter.test;

import java.util.Arrays;

import junit.framework.TestCase;

import org.junit.Test;

import eric.designpattern.adapter.AnalogSignal;
import eric.designpattern.adapter.AnalogToDigitAdapter;
import eric.designpattern.adapter.BinDigitSignal;
import eric.designpattern.adapter.DigitSignal;
import eric.designpattern.adapter.FloatAnalogSignal;

public class AdapterTest extends TestCase {
    private float[] analogData = { 0.2f, 1.4f, 3.12f, 0.9f };
    private byte[] binData = { 0, 1, 1, 0 };
    private float[] analogData2 = { 1.2f, 1.4f, 0.12f, 0.9f };

    @Test
    public void testAdapter() {
        AnalogSignal analogSignal = new FloatAnalogSignal(analogData);
        analogSignal.printAnalog();

        DigitSignal digitSignal = new BinDigitSignal(binData);
        digitSignal.printDigit();

        // adapter
        AnalogToDigitAdapter adAdapter = new AnalogToDigitAdapter(analogSignal);
        adAdapter.printDigit();
        assertTrue(Arrays.equals(digitSignal.getDigit(), adAdapter.getDigit()));

        adAdapter.setAnalogData(analogData2);
        adAdapter.printDigit();
        assertFalse(Arrays.equals(digitSignal.getDigit(), adAdapter.getDigit()));
    }
}

зависимость-через maven

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.13</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.13</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.16</version>
    </dependency>

Как проверить

просто запустите модульный тест.

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

реальные примеры могут быть языковым переводчиком или мобильным зарядным устройством. Подробнее здесь, в этом видео youtube:

Youtube-адаптер Дизайн Шаблон: введение

вы можете найти PHP-реализацию шаблона адаптера, используемого в качестве защиты от инъекционных атак здесь:

http://www.php5dp.com/category/design-patterns/adapter-composition/

одним из интересных аспектов шаблона адаптера является то, что он поставляется в двух вариантах: адаптер класса, полагающийся на множественное наследование, и адаптер объекта, полагающийся на композицию. Приведенный выше пример основан на композиции.

один реальный пример-Qt-Dbus.

qt-dbus имеет утилиту для генерации кода адаптера и интерфейса из предоставленного xml-файла. Вот шаги, чтобы сделать это.

 1. Create the xml file - this xml file should have the interfaces 
that can be viewed by the qdbus-view in the system either on 
the system or session bus.

    2.With the utility - qdbusxml2cpp , you generate the interface adaptor code. 
This interface adaptor does the demarshalling of the data that is 
received from the client. After demarshalling, it invokes the 
user defined - custom methods ( we can say as adaptee).

    3. At the client side, we generate the interface from the xml file. 
This interface is invoked by the client. The interface does the 
marshalling of the data and invokes the adaptor interface. As told 
in the point number 2, the adaptor interface does the demarshalling 
and calls the adaptee - user defined methods.

вы можете увидеть полный пример Qt-Dbus здесь -

http://www.tune2wizard.com/linux-qt-signals-and-slots-qt-d-bus/

реальным примером могут быть отчетные документы в приложении. Простой код, как здесь.

переходник я думаю, очень полезны для структуры программирования.

class WordAdaptee implements IReport{
    public void report(String s) {
        System.out.println(s +" Word");
    }
}

class ExcellAdaptee implements IReport{
    public void report(String s) {
        System.out.println(s +" Excel");
    }
}


class ReportAdapter implements IReport{
    WordAdaptee wordAdaptee=new WordAdaptee();
    @Override
    public void report(String s) {
        wordAdaptee.report(s);
    }
}

interface IReport {
    public void report(String s);
}

public class Main {
    public static void main(String[] args) {

        //create the interface that client wants
        IReport iReport=new ReportAdapter();

        //we want to write a report both from excel and world
        iReport.report("Trial report1 with one adaptee");  //we can directly write the report if one adaptee is avaliable 

        //assume there are N adaptees so it is like in our example
        IReport[] iReport2={new ExcellAdaptee(),new WordAdaptee()};

        //here we can use Polymorphism here  
        for (int i = 0; i < iReport2.length; i++) {
            iReport2[i].report("Trial report 2");
        }
    }
}

результаты:

Trial report1 with one adaptee Word
Trial report 2 Excel
Trial report 2 Word

вы можете использовать шаблон проектирования адаптера, когда вам приходится иметь дело с различными интерфейсами с аналогичным поведением (что обычно означает классы с аналогичным поведением, но с разными методами). Примером этого может быть класс для подключения к телевизору Samsung и еще один для подключения к телевизору Sony. Они имеют общее поведение, как открыть меню, воспроизведение, подключение к сети и т. д. Но каждая библиотека будет иметь разную реализацию (с разными названиями метод и подписывание.) Эти различные реализации конкретного поставщика называются Adaptee в диаграммах UML.

Итак, в вашем коде (называется клиент в UML-диаграммы), вместо того, чтобы жестко закодировать этот метод вызывает каждого поставщика (или Adaptee), затем вы можете создать общий интерфейс (называемый цель в диаграммах UML), чтобы обернуть эти похожие поведения и работать только с одним типом объекта.

The переходник будет затем реализовать цель интерфейс делегирует свои вызовы метода Adaptees, переданные переходник через конструктор.

чтобы вы поняли это в коде Java, я написал очень простой проект, используя точно такой же пример, упомянутый выше, используя адаптеры для работы с несколькими интерфейсами smart TV. Код небольшой, хорошо документированный и самоочевидный, поэтому копайте на нем, чтобы увидеть, как будет выглядеть реализация в реальном мире как.

просто загрузите код и импортируйте его в Eclipse (или вашу любимую IDE) в качестве проекта Maven. Вы можете выполнить код, запустив org.образец.Главный.java. Помните, что здесь важно понять, как классы и интерфейсы собираются вместе для разработки шаблона. Я также создал некоторые поддельные Adaptees в пакете com.третья сторона.библиотеки. Надеюсь на это помогает!

https://github.com/Dannemann/java-design-patterns

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

У вас есть приложение, которое считывает все строки в файле в структуру данных списка и отображает их в сетке (давайте вызовем базовый интерфейс хранилища данных IDataStore). Пользователь может перемещаться по этим данным, нажимая кнопки "первая страница", "Предыдущая страница", "Следующая страница", "последняя страница". Все работает нормально.

теперь приложение должно использоваться с производственными журналами, которые слишком велики для чтения в памяти, но пользователю все равно нужно перемещаться по нему! Одним из решений было бы реализовать кэш, который хранит первую страницу, следующую, предыдущую и последнюю страницы. То, что мы хотим, когда пользователь нажимает "Следующая страница", мы возвращаем страницу из кэш и обновить кэш; когда они нажимают последнюю страницу, мы возвращаем последнюю страницу из кэша. В фоновом режиме у нас есть filestream делает все волшебство. Таким образом, у нас есть только четыре страницы в памяти, а не весь файл.

вы можете использовать адаптер, чтобы добавить эту новую функцию кэша в приложение без уведомления Пользователя. Мы расширяем текущий IDataStore и называем его CacheDataStore. Если загружаемый файл большой, мы используем CacheDataStore. Когда мы делаем запрос для первого, Следующая, предыдущая и последняя страницы, информация направляется в наш кэш.

и кто знает, завтра Босс хочет начать читать файлы из таблицы базы данных. Все, что вам нужно сделать, это по-прежнему расширить IDataStore до SQLDataStore, как и для кэша, настроить соединение в фоновом режиме. Когда они нажимают кнопку "Следующая страница", вы создаете необходимый sql-запрос для извлечения следующих нескольких сотен строк из базы данных.

по сути, оригинальный интерфейс приложения не изменение. Мы просто адаптировали современные и интересные функции для работы с ним, сохраняя при этом устаревший интерфейс.

пример@Justice o не говорит о шаблоне адаптера четко. Расширяя свой ответ - У нас есть существующий интерфейс IDataStore, который использует наш потребительский код, и мы не можем его изменить. Теперь нас просят использовать классный новый класс из библиотеки XYZ, который делает то, что мы хотим реализовать, но, но, мы не можем изменить этот класс, чтобы расширить наш IDataStore, уже видели проблему ? Создание нового класса-адаптера, реализующего интерфейс, который ожидает наш потребительский код, т. е. IDataStore и с помощью класс из библиотеки, чьи функции нам нужно иметь-ADAPTEE, как член в нашем адаптере, мы можем достичь того, что мы хотели.

Это пример реализации адаптера:

interface NokiaInterface {
    chargementNokia(x:boolean):void
}


class SamsungAdapter implements NokiaInterface {
//nokia chargement adapted to samsung
    chargementNokia(x:boolean){
        const old= new SamsungCharger();
        let y:number = x ? 20 : 1;
        old.charge(y);
      }
}


class SamsungCharger {
      charge(x:number){
            console.log("chrgement x ==>", x);
      }
}


function main() {
      //charge samsung with nokia charger
      const adapter = new SamsungAdapter();
      adapter.chargementNokia(true);
}

Comments

    Ничего не найдено.