Wzorce projektowe – wzorzec Adapter

Często adapter jest wyjaśniany na podstawie gniazdka i wtyczki. Np. laptopa przystosowanego do polskich wtyczek sieciowych nie można bezpośrednio podłączyć do wtyczki sieciowej w Wielkiej Brytanii. Trzeba zastosować „przejściówkę” tudzież adapter który pozwoli na połączenie tych dwóch rzeczy.

Wzorzec adapter powstał w celu umożliwienia współpracy pomiędzy niedostosowanymi do siebie systemami. Wykorzystywany jest w szczegolności gdy chcemy aby nasza aplikacja współpracowała z zewnętrznymi bibliotekami/systemami których interfejsy nie są dostosowane do naszego systemu. Stosuje się go gdy wykorzystanie istniejącej klasy jest niemożliwe ze względu na jej niekompatybilny interfejs.

Adapter ma więc na celu takie połańczanie niekompatybilnych interesów bez modyfikacji aby cały system spójnie działał.

Najważniejszymi elementami tego wzorca są interfejs i klasa adaptera. Adapter nazywany Wrapper’em, wzorcem przejściowym należy do grupy wzorców strukturalnych. Opakowuje zaimplementowane metody interfejsu.

Implementacja tego wzorca może przybrać formę dziedziczenia

Wzorzec Adapter: dziedziczenie

lub kompozycji. Niezależnie od implementacji klient ma zawsze zależność z interfejsem.

Wzorzec Adapter: kompozycja

W tym wzorcu występują następujące elementy:

Target – definiuje interfejs wykorzystywany przez klienta.

Client – współpracuje z obiektami oraz wykorzystuje interfejs

Adaptee – istniejący interfejs który teraz powinien zostać przystosowany do współpracy z zewnętrznym interfejsem/systemem.

Adapter – interfejs który stanowi połączanie pomiędzy klientem a niekompatybilnym interfejsem.

W początkowym systemie zaimplementowano interfejs „Shape” z kilkoma metodami oraz klasy reprezentujące prostokąt oraz koło. Interface jest Targetem.

public interface Shape {
      void draw();
      void resize();
} 
 public class Rectangle implements Shape {
      @Override
      public void draw() {
      System.out.println("Drawing Rectangle");
     }
      @Override
      public void resize() {
      System.out.println("Resizing Rectangle");
      }
} 
 public class Circle implements Shape {
      @Override
      public void draw() {
      System.out.println("Drawing Circle");
      }
      @Override
      public void resize() {
      System.out.println("Resizing Circle");
      }
} 

Teraz klasa Drawing która pełni role klienta -> Client

public class Drawing {
 List shapes = new ArrayList();
 public Drawing() {
    super();
}
 public void addShape(Shape shape) {
    shapes.add(shape);
}
 public List getShapes() {
  return new ArrayList(shapes);
}
public void draw() {
  if (shapes.isEmpty()) {
     System.out.println("Nothing to draw!");
   } else {
      shapes.stream().forEach(shape -> shape.draw());
  }
}
 public void resize() {
  if (shapes.isEmpty()) {
      System.out.println("Nothing to resize!");
  } else {
      shapes.stream().forEach(shape -> shape.resize());
  }
 }
}

Oraz klasa wywoławcza „Main” wraz w wynikiem na konsoli.

public class Main {
 public static void main(String[] args) {
    System.out.println("Creating drawing of shapes...");
    Drawing drawing = new Drawing();
    drawing.addShape(new Rectangle());
    drawing.addShape(new Circle());
    System.out.println("Drawing...");
    drawing.draw();
    System.out.println("Resizing...");
    drawing.resize();
}
Wynik na konsoli:
Creating drawing of shapes...
Drawing...
Drawing Rectangle
Drawing Circle
Resizing...
Resizing Rectangle
Resizing Circle 


Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *