W świecie programowania często spotykamy się z sytuacjami, gdzie potrzebujemy współdziałać z bibliotekami, frameworkami lub modułami, które mają różne i niekompatybilne interfejsy. Wzorzec adaptera jest jednym z rozwiązań tego problemu, pozwalając na integrację obiektów, które na pierwszy rzut oka wydają się niezastąpione w swoich formach. Adapter stanowi swoiste "tłumaczenie" między różnymi interfejsami, pozwalając im na współpracę.
Cel i Zastosowanie Wzorca Adapter
Wyobraźmy sobie, że tworzysz aplikację monitorującą giełdę. Pobiera ona dane rynkowe z wielu źródeł w formacie XML, a następnie wyświetla ładnie wyglądające wykresy i diagramy. Na jakimś etapie postanawiasz wzbogacić aplikację poprzez dodanie inteligentnej biblioteki analitycznej innego producenta. Niestety, biblioteka ta działa wyłącznie z danymi w formacie JSON.
Można przerobić bibliotekę tak, aby obsługiwała XML, co może naruszyć działanie istniejącego kodu korzystającego z tej biblioteki. Co gorsza, możesz nie mieć dostępu do kodu źródłowego biblioteki, co czyni ten plan niewykonalnym.
W tej sytuacji z pomocą przychodzi wzorzec adaptera. Możemy stworzyć adapter, który będzie działał jako pośrednik między naszym kodem a biblioteką analityczną, konwertując dane z formatu XML do JSON i odwrotnie.
Jak to działa?
Adapter jest specjalnym obiektem, który opakowuje obiekt o niekompatybilnym interfejsie i zapewnia kompatybilny interfejs do użytku przez resztę naszego kodu. Oto jak można to zrobić:
Definiowanie Interface-u, który oczekuje nasz kod:
interface DataAnalyzer {
void analyzeData(String inputData);
}
Klasa implementująca interfejs w formacie JSON:
class JSONAnalyzer implements DataAnalyzer {
@Override
public void analyzeData(String jsonData) {
// Obsługa analizowania danych JSON
System.out.println("Analyzing JSON data: " + jsonData);
}
}
Klasa adaptera przekształcająca dane XML na JSON:
class XMLtoJSONAdapter implements DataAnalyzer {
private JSONAnalyzer jsonAnalyzer;public XMLtoJSONAdapter(JSONAnalyzer jsonAnalyzer) {
this.jsonAnalyzer = jsonAnalyzer;
}@Override
public void analyzeData(String xmlData) {
String jsonData = convertXMLtoJSON(xmlData);
jsonAnalyzer.analyzeData(jsonData);
}private String convertXMLtoJSON(String xmlData) {
// Implementacja konwersji XML do JSON
return "{json: "data"}";
}
}
Korzystanie z adaptera w naszym kodzie:
public class Main {
public static void main(String[] args) {
JSONAnalyzer jsonAnalyzer = new JSONAnalyzer();
DataAnalyzer adapter = new XMLtoJSONAdapter(jsonAnalyzer);String xmlData = "<data></data>";
adapter.analyzeData(xmlData);
}
}
Przykład z Prawdziwego Świata
Z życia codziennego świetnym przykładem adaptera jest adapter HDMI, który pozwala na podłączenie monitora HDMI do laptopa ze złączem VGA. Adapter ten tłumaczy sygnał HDMI na sygnał VGA, zapewniając kompatybilność między dwoma urządzeniami o różnych interfejsach.
Kiedy Stosować Adapter?
- Gdy musisz użyć istniejącej klasy, ale jej interfejs nie pasuje do reszty kodu.
- Gdy chcesz utworzyć klasy wielokrotnego użytku, które współpracują ze sobą, ale mają różne interfejsy.
- Gdy korzystasz z bibliotek firm trzecich i potrzebujesz spójności w interfejsach swojego kodu.
Wzorzec adaptera ułatwia integrację i zwiększa elastyczność w zarządzaniu kodem, zwłaszcza w dużych i złożonych systemach, gdzie różne moduły mogą wyewoluować niezależnie od siebie.
Wnioski
Adapter to potężny wzorzec projektowy, umożliwiający łączenie niekompatybilnych interfejsów w sposób elastyczny i efektywny. Jest niezastąpiony, szczególnie gdy mamy do czynienia z kodem, którego nie możemy zmienić, lub gdy różne części systemu muszą współpracować mimo różnic w interfejsach.