[Design Pattern] Strukturelle Muster: Adapter


#1
Hallo,

dieser Beitrag demonstriert das Strukturelle Muster (Structural Pattern): Adapter

Der Bergriff Adapter ist einem sicherlich schon einmal in Zusammenhang mit unterschiedlichen Stromanschlüssen begegnet.
Will man einen Stecker mit Anschlussform A in eine Steckdose stecken, welche nur Anschlussform B erlaubt, so braucht man einen Adapter welcher die Anschlussform A mit der Anschlussform von B kompatibel macht.

Bei dem Design Pattern Adapter verhält es sich nun analog:
Die Aufgabe eines Adapters ist es Klassen mit technisch inkompatibler Schnittstelle miteinander kompatibel zu machen.

Dazu hier mal ein kleines Beispiel:
Java:
package de.tutorials.design.patterns.structural;

import org.jpatterns.gof.AdapterPattern.Adaptee;
import org.jpatterns.gof.AdapterPattern.Adapter;
import org.jpatterns.gof.AdapterPattern.Variation;

public class AdapterExample {
  
  public static void main(String[] args) {
    
    simpleExample();
    
    System.out.println("####");
    
    businessCodeExample();
   
  }

  private static void simpleExample() {
    //here our power connector / plug metaphor 
       
    class PlugConnectorA{}
    
    class PowerSocketA{
      public void plug(PlugConnectorA a){
        System.out.println("plugged: " + a);
      }
    }
    
    PowerSocketA powerSocketA = new PowerSocketA();
    //powerSocketA.plug(new PlugConnectorB()); //compiler error  
        
    @Adaptee
    class PlugConnectorB{}
    
    @Adapter
    class PlugConnectorAdapter extends PlugConnectorA{
      
      final PlugConnectorB adaptee;
      
      public PlugConnectorAdapter(PlugConnectorB adaptee) {
        this.adaptee = adaptee;
      }
      
      @Override
      public String toString() {
        return "Adapted: " + this.adaptee;
      }
    }
    
    powerSocketA.plug(new PlugConnectorAdapter(new PlugConnectorB())); //successfully adapted
  }

  static void businessCodeExample() {
    
    //This is the businessService implementation we want to use:
    LegacyBusinessService legacyBusinessService = new LegacyBusinessService();
    
    //This is the user of the businessService
    BusinessServiceClient client = new BusinessServiceClient();
    
    //client.use(legacyBusinessService); //would produce a compile time error since LegacyBusinessService 
                                         // is not compatible to the required BusinessService-Interface
    
    /*
     * The solution: we define an adapter class that bridges the gap between the two incompatible interfaces.
     * 
     * One particular variant of the adapter is an ObjectAdapter:
     * The Adapter class implements the required interface and
     * wraps an Object (the so called adaptee) to which all interface method 
     * calls on the adapter will be delegated.
     */
    client.use(new BusinessServiceObjectAdapter(legacyBusinessService));
    
    /*
     * Another variant of the adapter pattern is a ClassAdapter:
     * 
     * Instead of using an delegate instance we subclass the adaptee class and implement 
     * the required interface. In the implementation of the interface method we delegate to
     * methods of the adaptee class.
     */
    client.use(new BusinessServiceClassAdapter());
  }

  static class BusinessServiceClient{
    public void use(BusinessService businessService){
      businessService.businessMethod();
    }
  }
  
  /**
   * The required business interface
   */
  static interface BusinessService {
    void businessMethod();
  }
  
  /**
   * An old business service implementation that we have to use...  
   */
  @Adaptee
  static class LegacyBusinessService{
    public void legacyBusinessMethod(){
      System.out.println("businessOp");
    }
  }
  
  @Adapter(value=Variation.OBJECT)
  static class BusinessServiceObjectAdapter implements BusinessService{
    
    private final LegacyBusinessService adaptee;

    public BusinessServiceObjectAdapter(LegacyBusinessService adaptee) {
      this.adaptee = adaptee;
    }

    @Override
    public void businessMethod() {
      adaptee.legacyBusinessMethod();
    }
  }
  
  @Adapter(value=Variation.CLASS)
  static class BusinessServiceClassAdapter extends LegacyBusinessService implements BusinessService{
    
    @Override
    public void businessMethod() {
      super.legacyBusinessMethod();
    }
    
  }  
 
}
Ausgabe:
Code:
plugged: Adapted: de.tutorials.design.patterns.structural.AdapterExample$1PlugConnectorB@23fc4bec
####
businessOp
businessOp
Gruß Tom