adapter-Dowolny prawdziwy przykład wzoru adaptera [zamknięty]


84

Chcę zademonstrować mojemu zespołowi użycie wzorca adaptera . Przeczytałem wiele książek i artykułów online. Wszyscy cytują przykład, który jest przydatny do zrozumienia koncepcji (kształt, karta pamięci, adapter elektroniczny itp.), Ale nie ma prawdziwego studium przypadku.

Czy możesz udostępnić studium przypadku dotyczące wzoru adaptera?

ps Próbowałem przeszukać istniejące pytania na stackoverflow, ale nie znalazłem odpowiedzi, więc publikowałem je jako nowe pytanie. Jeśli wiesz, że jest już na to odpowiedź, przekieruj.


4
Cóż, jeśli chcesz to pokazać. Powinieneś mieć gotowy przykład tego w swoim środowisku, a właściwie kilka. W przeciwnym razie dlaczego miałbyś chcieć to demo?
Tony Hopkinson

1
Kilka przykładów tutaj. stackoverflow.com/questions/1673841/…
r4.

1
@TonyHopkinson Celem jest uświadomienie ludziom tego wzorca projektowego na prawdziwym przykładzie.
AksharRoop

10
@AksharRoop. Wzorzec projektowy ma być rozwiązaniem problemu, a nie rozwiązaniem szukającym problemu. Najlepszy przykład to ten z twojego własnego „świata”.
Tony Hopkinson

1
@TonyHopkinson Być może użyłem tu niewłaściwego terminu demonstracyjnego, ale miałem na myśli wyjaśnienie koncepcji tego wzoru na dobrym przykładzie. Zgadzam się, że powinienem znaleźć ten w moim własnym systemie ...
AksharRoop

Odpowiedzi:


77

Wiele przykładów adapterów jest banalnych lub nierealnych ( Rectangle vs. LegacyRectangle, Ratchet vs. Socket , SquarePeg vs. RoundPeg , Duck vs. Turkey ). Co gorsza, wiele z nich nie pokazuje wielu adapterów dla różnych adapterów ( ktoś zacytował Arrays.asList języka Java jako przykład wzorca adaptera ). Dostosowanie interfejsu tylko jednej klasy do pracy z inną wydaje się słabym przykładem wzorca GoF Adapter. Ten wzorzec wykorzystuje dziedziczenie i polimorfizm, więc można by się spodziewać dobrego przykładu pokazującego wiele implementacji adapterów dla różnych adapterów .

Najlepszym przykładem znalazłem jest w rozdziale 26 Zastosowanie UML i wzorce: Wprowadzenie do Object-Oriented Analysis and Design i Iteracyjne Rozwoju (3rd Edition) . Poniższe obrazy pochodzą z materiału instruktorskiego udostępnionego na serwerze FTP do książki.

Pierwsza z nich pokazuje, w jaki sposób aplikacja może korzystać z wielu implementacji (adapterów), które są podobne funkcjonalnie (np. Kalkulatory podatkowe, moduły księgowe, usługi autoryzacji kredytu itp.), Ale mają różne API. Chcemy uniknąć zakodowania na stałe naszego kodu warstwy domeny w celu obsługi różnych możliwych sposobów obliczania podatku, obsługi posprzedażnej, autoryzacji żądań kart kredytowych itp. Są to wszystkie zewnętrzne moduły, które mogą się różnić i dla których nie możemy modyfikować kod. Adapter pozwala nam na stałe kodowanie w adapterze, podczas gdy nasz kod warstwy domeny zawsze używa tego samego interfejsu (interfejs IWh AnyAdapter).

Ryc.26.1

Na powyższym rysunku nie widzimy rzeczywistych adapterów. Jednak na poniższym rysunku pokazano, w jaki sposób wykonywane jest polimorficzne wywołanie postSale(...)w interfejsie IAccountingAdapter, które skutkuje zaksięgowaniem sprzedaży za pośrednictwem protokołu SOAP do systemu SAP.

Ryc.26.2


ten przykład użycia sesji też jest całkiem dobry (chociaż implementacja nie jest do końca poprawna, myślę, że przy użyciu statystyk): community.sitepoint.com/t/phpunit-testing-cookies-and-sessions/…
Alejandro Moreno


50

Jak zmienić Francuza w normalną osobę ...

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

Przykład

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

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

19
Jestem Francuzem i czuję się urażona, że ​​nie uważasz mnie za prawdziwą osobę. (JK)
ZeroUltimax

13
@ZeroUltimax Jestem prawie pewien, że ten kod nie skompiluje się w Quebecu.
Fuhrmanator

Każdy programista bez znajomości adapterów z łatwością rozwiązałby problem. W jaki sposób znajomość teorii adapterów pomaga zaoszczędzić czas lub ulepszyć rozwiązanie? Czy ostatecznym celem jest użycie specjalnej klasy zamiast używania tylko metody?
Rowan Gontier

A co, jeśli nie kontrolujesz interfejsu i musisz dostosować jedną ze swoich zajęć do biblioteki innej firmy? Wiele innych dobrych powodów, które są poza zakresem tej odpowiedzi.
CountZero

3
To jest najzabawniejszy - i prawdopodobnie jeden z najbardziej przystępnych - przykładów użycia wzorca adaptera, z jakim kiedykolwiek się spotkałem.
Mass Dot Net


13

Oto przykład, który symuluje konwersję analog datado formatu digit data.

Dostarcza adapter, który konwertuje zmiennoprzecinkowe dane cyfrowe na dane binarne, prawdopodobnie nie jest przydatny w świecie rzeczywistym, po prostu pomaga wyjaśnić koncepcję wzorca adaptera.


Kod

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

Kod - przypadek testowy

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

Zależność - via 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>

Jak przetestować

Po prostu uruchom test jednostkowy.


7

Wzorzec adaptera działa jako most między dwoma niekompatybilnymi interfejsami. Ten wzorzec obejmuje jedną klasę zwaną adapterem, która jest odpowiedzialna za komunikację między dwoma niezależnymi lub niekompatybilnymi interfejsami.

Przykładami ze świata rzeczywistego może być tłumacz języka lub mobilna ładowarka. Więcej tutaj w tym wideo z YouTube:

Youtube - Wzorzec projektowy adaptera: Wprowadzenie


3

Wzorca projektowego Adapter można użyć, gdy masz do czynienia z różnymi interfejsami o podobnym zachowaniu (co zwykle oznacza klasy o podobnym zachowaniu, ale z różnymi metodami). Przykładem może być klasa do podłączenia do telewizora Samsung i inna do podłączenia do telewizora Sony. Będą mieć wspólne zachowanie, takie jak otwieranie menu, rozpoczynanie odtwarzania, łączenie się z siecią itp., Ale każda biblioteka będzie miała inną implementację (z różnymi nazwami metod i podpisami). Te różne implementacje specyficzne dla dostawców są nazywane Adaptee w diagramach UML.

Tak więc w swoim kodzie (nazywanym klientem na diagramach UML), zamiast sztywnego kodowania wywołań metod każdego dostawcy (lub Adaptee ), można następnie utworzyć ogólny interfejs (nazywany docelowym w diagramach UML), aby opakować te podobne zachowania i działać tylko z jednym rodzajem obiektu.

Te adaptery będą następnie wdrożyć docelowy interfejs delegowanie swoich połączeń metodę do Adaptees , które są przekazywane do Adaptery przez konstruktora.

Abyś mógł to zrealizować w kodzie Java, napisałem bardzo prosty projekt, używając dokładnie tego samego przykładu wymienionego powyżej, używając adapterów do obsługi wielu interfejsów Smart TV. Kod jest mały, dobrze udokumentowany i nie wymaga objaśnień, więc zapoznaj się z nim, aby zobaczyć, jak wyglądałaby implementacja w świecie rzeczywistym.

Po prostu pobierz kod i zaimportuj go do Eclipse (lub swojego ulubionego IDE) jako projekt Maven. Możesz wykonać kod, uruchamiając org.example.Main.java . Pamiętaj, że ważne jest, aby zrozumieć, w jaki sposób klasy i interfejsy są łączone razem w celu zaprojektowania wzorca. Stworzyłem także kilka fałszywych Adaptees w pakiecie com.thirdparty.libs . Mam nadzieję, że to pomoże!

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


2

Jednym z prawdziwych przykładów jest Qt-Dbus.

Qt-dbus zawiera narzędzie do generowania adaptera i kodu interfejsu z dostarczonego pliku xml. Oto kroki, aby to zrobić.

 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.

Możesz zobaczyć pełny przykład Qt-Dbus tutaj -

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


2

Implementację PHP wzorca Adapter używanego do obrony przed atakami typu injection można znaleźć tutaj:

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

Jednym z interesujących aspektów wzorca adaptera jest to, że występuje on w dwóch odmianach: adapter klasy korzystający z wielokrotnego dziedziczenia oraz adapter obiektów zależny od kompozycji. Powyższy przykład opiera się na kompozycji.



2

Wzorce projektowe adaptera pomagają w konwersji interfejsu jednej klasy na interfejs oczekiwany przez klienta.

Przykład: Masz usługę, która zwraca pogodę (w stopniach Celsjusza), przekazując nazwę miasta jako wartość wejściową. Teraz załóżmy, że klient chce podać kod pocztowy jako dane wejściowe i oczekuje w zamian temperatury miasta. Aby to osiągnąć, potrzebujesz adaptera.

public interface IWetherFinder {
    public double getTemperature(String cityName);
}

class WeatherFinder implements IWetherFinder{
   @Override
   public double getTemperature(String cityName){
     return 40;
   }
}

interface IWeatherFinderClient
{
   public double getTemperature(String zipcode);
}  

public class WeatherAdapter implements IWeatherFinderClient {

    @Override
    public double getTemperature(String zipcode) {

        //method to get cityname by zipcode 
        String cityName = getCityName(zipcode);

        //invoke actual service
        IWetherFinder wetherFinder = new WeatherFinder();
        return wetherFinder.getTemperature(cityName);
    }

    private String getCityName(String zipCode) {
        return "Banaglore";
    }
}

0

Prawdziwym przykładem może być raportowanie dokumentów w aplikacji. Prosty kod, jak tutaj.

Myślę, że adaptery są bardzo przydatne w strukturze programowania.

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

Wyniki będą:

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

1
W rzeczywistości jest to serwer proxy. Adapter i adapter mają różne interfejsy. Nie implementują tego samego interfejsu. To właśnie robi proxy.
dvallejo

To nie jest wzór adaptera. Wzorzec adaptera jest używany do implementacji interfejsu docelowego, którego adapter nie implementuje.
FedericoG

0

Użyj adaptera, jeśli masz interfejs, którego nie możesz zmienić, ale którego musisz użyć. Zobacz, jak jesteś nowym facetem w biurze i nie możesz zmusić siwych włosów do przestrzegania twoich zasad - musisz się do nich dostosować. Oto prawdziwy przykład z prawdziwego projektu, nad którym kiedyś pracowałem, w którym interfejs użytkownika jest podany.

Masz aplikację, która wczytuje wszystkie wiersze w pliku do struktury danych List i wyświetla je w siatce (nazwijmy bazowy interfejs magazynu danych IDataStore). Użytkownik może poruszać się po tych danych, klikając przyciski „Pierwsza strona”, „Poprzednia strona”, „Następna strona”, „Ostatnia strona”. Wszystko dziala.

Teraz aplikacja musi być używana z dziennikami produkcyjnymi, które są zbyt duże, aby wczytać je do pamięci, ale użytkownik nadal musi się po nich poruszać! Jednym z rozwiązań byłoby zaimplementowanie pamięci podręcznej przechowującej pierwszą stronę, następną, poprzednią i ostatnią stronę. Chcemy, aby kiedy użytkownik kliknął „Następna strona”, zwracamy stronę z pamięci podręcznej i aktualizujemy pamięć podręczną; kiedy klikną ostatnią stronę, zwracamy ostatnią stronę z pamięci podręcznej. W tle mamy strumień plików, który robi całą magię. W ten sposób mamy w pamięci tylko cztery strony, a nie cały plik.

Możesz użyć adaptera, aby dodać tę nową funkcję pamięci podręcznej do aplikacji bez zauważenia tego przez użytkownika. Rozszerzamy obecny IDataStore i nazywamy go CacheDataStore. Jeśli plik do załadowania jest duży, używamy CacheDataStore. Kiedy wysyłamy żądanie dotyczące pierwszej, następnej, poprzedniej i ostatniej strony, informacje są kierowane do naszej pamięci podręcznej.

A kto wie, jutro szef chce zacząć czytać pliki z tabeli bazy danych. Wszystko, co musisz zrobić, to nadal rozszerzać IDataStore do SQLDataStore, tak jak w przypadku Cache, konfigurując połączenie w tle. Kiedy klikną Next page, wygenerujesz niezbędne zapytanie sql, aby pobrać następne kilkaset wierszy z bazy danych.

Zasadniczo oryginalny interfejs aplikacji nie uległ zmianie. Po prostu dostosowaliśmy nowoczesne i fajne funkcje, aby działały, zachowując stary interfejs.


Nie rozumiem? Wygląda na to, że właśnie użyłeś istniejącego interfejsu i zaimplementowałeś metody? Gdzie jest inny interfejs, do którego należy się dostosować, i klasa adaptera?
berimbolo

@berimbolo Twoje zamieszanie jest uzasadnione, ponieważ powyższy przykład nie mówi wyraźnie o wzorze adaptera.
rahil008

0

Przykład @Justice o nie mówi wyraźnie o wzorze adaptera. Rozszerzając jego odpowiedź - Mamy już interfejs IDataStore, z którego korzysta nasz kod konsumencki i nie możemy go zmienić. Teraz jesteśmy proszeni o użycie nowej, fajnej klasy z biblioteki XYZ, która robi to, co chcemy zaimplementować, ale ale nie możemy zmienić tej klasy w celu rozszerzenia naszego IDataStore, widzisz już problem? Tworząc nową klasę - ADAPTER, która implementuje interfejs, którego oczekuje nasz konsumencki kod, czyli IDataStore i wykorzystując klasę z biblioteki, której cechy musimy mieć - ADAPTEE, jako członek naszego ADAPTERA, możemy osiągnąć to, co chcieliśmy.



0

Przykład z frameworka Yii to: Yii używa wewnętrznej pamięci podręcznej wykorzystując interfejs ICache. https://www.yiiframework.com/doc/api/1.1/ICache

którego podpis jest taki: -

abstract public boolean set(string $id, mixed $value, integer $expire=0, ICacheDependency $dependency=NULL)
abstract public mixed get(string $id)

Powiedzmy, że chciałbyś użyć wewnątrz projektu Yii biblioteki pamięci podręcznej symfony https://packagist.org/packages/symfony/cache z jej interfejsem pamięci podręcznej, definiując tę ​​usługę w konfiguracji komponentów usług Yii (lokalizator usług) https: / /github.com/symfony/cache-contracts/blob/master/CacheInterface.php

    public function get(string $key, callable $callback, float $beta = null, array &$metadata = null);

Widzimy, że pamięć podręczna symfony ma interfejs tylko z metodą get, brakuje metody set i innej sygnatury dla metody get, ponieważ Symfony używa metody get również jako setera, gdy dostarcza drugi parametr wywoływalny.

Ponieważ rdzeń Yii wewnętrznie korzysta z tej pamięci podręcznej / interfejsu Yii, przepisanie wywołań do tego interfejsu jest trudne (rozszerzenie Yii / YiiBase), jeśli nie niemożliwe.

Poza tym pamięć podręczna Symfony nie jest naszą klasą, więc nie możemy przepisać jej interfejsu, aby pasował do interfejsu pamięci podręcznej Yii.

Oto więc wzór adaptera na ratunek. Napiszemy mapping = pośredni adapter, który zmapuje wywołania interfejsu pamięci podręcznej Yii do interfejsu pamięci podręcznej Symfony

Wyglądałby tak

    class YiiToSymfonyCacheAdapter implements \Yii\system\caching\ICache
    {
        private \Symfony\Contracts\Cache\CacheInterface $symfonyCache;

        public function __construct(\Symfony\Contracts\Cache\CacheInterface $symfonyCache)
        {
            $this->symfonyCache = $symfonyCache;
        }

      
      public boolean set(string $id, mixed $value, integer $expire=0, ICacheDependency 
       $dependency=NULL) 
      {

          // https://symfony.com/doc/current/cache.html
          return $this->symfonyCache->get(
              $id, 
              function($item) { 
              // some logic .. 
               return $value; 
              }
          );

//          https://github.com/symfony/cache/blob/master/Adapter/MemcachedAdapter.php
// if a class could be called statically, the adapter could call statically also eg. like this
//          return \Symfony\Component\Cache\Adapter\MemcacheAdapter::get(
//              $id, 
//              function($item) { 
//              // some logic .. 
//               return $value; 
//              }
          );
       }

       public mixed get(string $id) 
       {
           // https://github.com/symfony/cache/blob/master/Adapter/FilesystemAdapter.php 
           // if a class could be called statically, the adapter could call statically also eg. like this
           // \Symfony\Component\Cache\Adapter\FileSystemAdapter::get($id)
           return $this->symfonyCache->get($id) 
       }
    } 


-1

Oto przykład implementacji adaptera:

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);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.