What is adapter pattern?

  • As the name suggests, adapter pattern lets one object to adapt to the other object, making it function as if it is that object. Adater pattern acts as a connector between two incompatible interfaces that otherwise cannot be connected directly.

When do I use it?

  • When you want to make an object do an action different than its original one. Then you might wonder, why bother using that object at all? Good quesiton. This patterns makes sense only when the adapting functionality takes only a small portion out of the entire functionalities.

  • Taking a real life example, you bought a chargeable flashlight at a Korean market, but you want to use it when travelling in Europe, per say. Then you probably want to buy a pluggable adapter that wraps the plug, changing its shape at the end. Adding this adapter does NOT change the nature of the flashlight’s functionality, while making it ‘chargeable’ anywhere in the world. (FYI, I might be wrong as to what voltages is norm in Europe and Korea.. that’s not the point anyways.)

Code examples

public interface Chargeable {
    double getOutlet();
}

public interface ChargeableAdapter {
    double getOutlet();
}    
  • First, have the two interfaces ready.
public class KoreanPlug implements Chargeable {
    @Override
    public double getOutlet() {
        return 220;
    }
}
  • KoreanPlug’s outlet is fit for 220V, which is not fit for 110V
public class EuropeOutletAdapter implements ChargeableAdapter {
    private Chargeable plug;

    public EuropeOutletAdapter(Chargeable plug) {
        this.plug = plug;
    }

    @Override
    public double getOutlet() {
        return convertOutlet(plug.getOutlet());
    }

    private double convertOutlet(double outlet){
        return speed/2; //converts to 110V
    }
}
  • The EuropeOutletAdapter implements ChargeableAdapter, and has plug as one of its member variables.
  • When initializing the object, it has the implementation of Chargeable as a parameter.
  • When getOutlet is called, it converts internally the outlet of member variable, and returns the result.
public class Main {
    public static void main(String[] args) {
        Chargeable plugIBought = new KoreanPlug(); //220
        System.out.println(plugIBought.getOutlet());

        ChargeableAdapter pigNose = new EuropeOutletAdapter(plugIBought);
        System.out.println(pigNose.getOutlet()); //110
    }
}
220.0
110.0

Conclusion

  • Adapter pattern is really not a big deal. But one must think about why this pattern can be useful. Suppose an object A has to perform what another class’s object B has to perform. You can either
    1. Add a new method to A whenever A has to do something undefined.
    2. Make a adapter interface and implement it like above.
  • In a long term (and even for a short term, for clarity’s sake), following second option is far more beneficial. First and foremost second approach leaves the original interface intact, not harming any of its implementing classes thereafter. Secondly, developers can understand the code mucn better by seeing an adapter class adapting an object to perform an otherwise undefined action.

  • This was it, and will add some more concrete examples whenever I find any!