Press "Enter" to skip to content

Wzorce projektowe – Adapter

Dzisiaj na ruszt rzucimy adapter. Adapter służy do adaptacji (genius…) części kodu działającego ze starą wersją biblioteki w taki sposób, aby działał z nową wersją.

Wzorzec Adapter dokonuje konwersji interfejsu danej klasy do postaci innego interfejsu, zgodnego z oczekiwaniami klienta. Adapter pozwala na wzajemną współpracę klas, które ze względu na niekompatybilne interfejsy wcześniej nie mogły ze sobą współpracować.

Definicja zaczerpnięta z książki Rusz głową! Wzorce projektowe

Schemat wzorca

Zmiana interfejsu Enumeration na Iterator

Dzisiaj zrobimy sobie przykład, który może się bardziej przydać w życiu codziennym. Otóż za pomocą wzorca adapter sprawimy, aby stare klasy Javy (takie jak Vector, Stack, Hashtable, etc.) również współpracowały z nowym interfejsem Iterator. Popatrzmy na implementację tych dwóch interfejsów:

Schematy interfejsów Enumeration oraz Iterator

Po przyjrzeniu się obu interfejsom, można zauważyć pewne podobieństwa – oba interfejsy posiadają metody do sprawdzenia, czy jeszcze istnieje jakiś element w kolekcji oraz metodę do pobierania następnego elementu. Różni je natomiast to, że Enumeration nie posiada metody do kasowania elementu z kolekcji, ale i z tym sobie poradzimy (patrz implementacja 😉 ).
A teraz czas na schemat zaimplementowanego wzorca:

Implementacja wzorca

Mamy już w pełni działający projekt naszego adaptera. Czas zaimplementować go w kodzie i sprawdzić jak działa.

Podsumowanie

Dzisiaj szybko poszło z wzorcem, ale to dlatego, że jest to bardzo prosty wzorzec. Często w życiu codziennym spotykamy adaptery w różnych postaciach, adapter zmieniający złącze audio z jednego rodzaju na inny, adapter do gniazdka z angielskiego na polski, lub odwrotnie.
Nie wspomniałem jeszcze o jednej ciekawej funkcji adapterów – można je pisać w dwie strony (tzn. dwustronne adaptery). W językach takich jak C++ wykorzystuje się do tego możliwość wielodziedziczenia (nie musimy implementować metod), w Javie podobny efekt można otrzymać, stosując implementację dwóch interfejsów oraz implementację wszystkich koniecznych metod.

github

Przykład uruchomienia aplikacji

public class Startup {
    public static void main(String[] args) {
        Vector<String> strings = new Vector<>();
        strings.add("Ala");
        strings.add("ma");
        strings.add("kota");
        EnumerationAdapter enumerationAdapter = new EnumerationAdapter(strings.elements());
        while (enumerationAdapter.hasNext()) {
            System.out.println(enumerationAdapter.next());
        }
    }
}

Wyjście aplikacji:

Ala
ma
kota