Adapter Design Pattern

COMP 310  Java Resources  Eclipse Resources

(Back to Design Patterns)

Note:

Do not confuse the abstract concept of an "interface" (the set of methods/behaviors that one object expects to see when communicating with another object) with the Java interface type in the following discussion. In general, we will be talking about the interface concept and we will explicitly refer to an interface type when we mean something like the Java interface type.
Definition 1: Adapters
Adapters are used to enable objects with different interfaces to communicate with each other.

Adapters come in two flavors, object adapters and class adapters.  These two methods embody the difference between the use of inheritance and composition to solve problems.

Object Adapters

Object adapters use a compositional technique to adapt one interface to another.    The adapter inherits the target interface that the client expects to see, while it holds an instance the adaptee.   When the client calls the request() method on its target object (the adapter), the request is translated into the corresponding specific request on the adaptee. The target may be of an abstract class type (shown below) or of an interface type. In either case, the the forwarded request would be an overridden abstract method in the concrete adapter implementation.

Figure 1: Object adapter implementation of the Adapter Design Pattern.
Figure 1 (graphics1.png)

Object adapters enable the client and the adaptee to be completely decoupled from each other.   Only the adapter knows about both of them.

Object Adapters Using Anonymous Inner Classes

One of the more common techniques for implementing object adapters in Java is to use anonymous inner classes. The technique is especially popular in creating adapters for Model-View-Controller (MVC) architecture implementations. For example, in the Controller of an MVC, the Model and the View objects need to be instantiated, each with adapters that connect to the other. By creating fields that hold references to the model and the view respectively, anonymous inner class implementations of the adapters can close over those fields (due to the lexical scoping properties of anonymous inner classes), thus enabling an adapter to reference its adaptee (model or view) without the need of an explicit field in the adapter itself.

Pseduo-code MVC implementation using anonymous inner class adapters

public class Controller {

    private Model myModel;
    private View myView;

    public Controller() {
        myModel = new Model( new IModel2ViewAdapter() {
            public void request2View() {
                myView.handleModelRequest();  // myView is in scope!
            }
        });

        myView = new View( new IView2ModelAdapter() {
            public void request2Model() {
                myModel.handleViewRequest(); // myModel is in scope!
            }
        });
    }
} 

Because the anonymous inner class adapters close over the fields of the Controller, those fields are implicitly fields of the adapters and thus serve as the adapter's adaptees.

Notice how this technique neatly solves the problem of establishing two-way communications between two objects, without the need for "setter" method(s). The model and the view can be truly symmetrically decoupled.

Class Adapters

Class adapters use multiple inheritance to achieve their goals.   As in the object adapter, the class adapter inherits the interface of the client's target.   However, it also inherits the interface of the adaptee as well.   Since Java does not support true multiple inheritance, this means that one of the interfaces must be inherited from a Java interface type.   Note that either or both of the target or adaptee interfaces could be Java interface types. Below, the diagram shows the target as an abstract class type and the adaptee as an interface type.   The request to the target is simply rerouted to the specific request that was inherited from the adaptee interface.

Figure 2: Class adapter implementation of the Adapter Design Pattern.
Figure 2 (graphics2.png)

Note that class adapters have a problem with name conflicts if methods of the same signature exist on both the target and the adaptee.  Note that just because two objects have methods that have the same signature (syntax), it does not guarantee that the two methods have the same meaning or behavior (sematics).    That is, the two methods do not necessarily map directly to each other.   Object adapters do not have this problem.

Comparison Between Object and Class Adapters

Class adapters are simpler than object adapters in that they involve fewer classes and are useful if total decoupling of the client and adaptee is not needed. Object adapters give better decoupling and are thus more flexible.

References

  1. Gamma, Helm, Johnson and Vlissides. (1995). Design Patterns, Elements Of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley.

 


Originally published in Connexions (CNX): https://web.archive.org/web/20130105080735/http://cnx.org/content/m14623/latest/

 

© 2023 by Stephen Wong