Подтвердить что ты не робот

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

Я хочу продемонстрировать использование моей команды в Adapter Pattern. Я читал много книг и статей в Интернете. Все приводят пример, который полезен для понимания концепции (Shape, Memory Card, Electronic Adapter и т.д.), Но нет реального изучения конкретных случаев.

Можете ли вы поделиться любым примером изучения шаблона адаптера?

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

4b9b3361

Ответ 1

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

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

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

Fig. 26.1

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

Fig. 26.2

Ответ 2

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

 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));

Ответ 3

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

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

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

enter image description here

Ответ 4

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

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


код

AnalogSignal.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>

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

Просто запустите unit test.

Ответ 5

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

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

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

Ответ 6

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

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

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

Ответ 7

Одним из реальных примеров является 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/

Ответ 8

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

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

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

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

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

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

Ответ 9

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

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

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

Ответ 10

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

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

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

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

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

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

Ответ 11

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

Ответ 13

Есть много реальных примеров использования адаптера

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

enter image description here

enter image description here

Ответ 14

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

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);
}