11

While reading up on the Class Adapter pattern in Head First Design Patterns, I came across this sentence:

class adapter... because you need multiple inheritance to implement it, which is not possible in Java

Just to experiment, I tried the following:

interface MyNeededInterface{
    public void operationOne(MyNeededInterface other);
    public MyNeededInterface operationTwo();
}

public class ThirdPartyLibraryClass{
    public void thirdPartyOp();
}

Suppose I create :

class ThirdPartyWrapper extends ThirdPartyLibraryClass implements MyNeededInterface{

    @Override
    public void operationOne(ThirdPartyWrapper other){
        this.thirdPartyOp();
        dosomeExtra();
    }
    @Override
    public ThirdPartyWrapper operationTwo(){
        int somevalue = doSomeThingElse();
        return new ThirdPartyWrapper(somevalue);
    }
}

In my code, I can use:

MyNeededInterface myclass = createThirdPartyWrapper();
myclass.operationOne(someobj);
...

Is this not the Class Adapter pattern?

blacktide
  • 10,654
  • 8
  • 33
  • 53
markjason72
  • 1,653
  • 8
  • 27
  • 47

5 Answers5

11

The class adapter pattern is not possible in Java because you can't extend multiple classes. So you'll have to go with the adapter pattern which uses composition rather than inheritance.

An example of the adapter pattern through composition can be found below:

interface Duck
{
    public void quack();
}

class BlackDuck implements Duck
{
   public void quack() { }
}

class Turkey
{
    public void gobble() { }
}

class TurkeyAdapter implements Duck
{
    private Turkey t;

    public TurkeyAdapter(Turkey t)
    {
        this.t = t;
    }

    public void quack()
    {
        // A turkey is not a duck but, act like one
        t.gobble();
    }
}

Now you can pass a Turkey to a method which is expecting a Duck through the TurkeyAdapter.

class DuckCatcher
{
    public void catch(Duck duck) { }
}

By using the adapter pattern the DuckCatcher is now also able to catch Turkey(Adapter)s and Ducks.

Kevin
  • 5,626
  • 3
  • 28
  • 41
  • 1
    This is the object adapter pattern. The OP wants to attempt implementing the class adapter pattern. – Vineet Reynolds Jun 10 '11 at 11:42
  • 1
    @Vineet: Could you expand? I'm not sure what the difference is between both? I thought there was just one general 'adapter pattern'. – Kevin Jun 10 '11 at 11:44
  • 2
    the Head First Patterns book, discusses the variant where inheritance (and not composition) is used to implement the class adapter. This is possible in C++ - see [this example](http://sourcemaking.com/design_patterns/adapter/cpp/1) for instance. – Vineet Reynolds Jun 10 '11 at 11:49
  • @Vineet: Ah I see, thanks for the link. The adapter pattern through inheritance would be impossible in Java though. – Kevin Jun 10 '11 at 12:00
  • don't agree that Class Adapter is not possible; check out this link http://en.wikipedia.org/wiki/Adapter_pattern – rai.skumar Mar 06 '13 at 07:54
  • I'm with @rai.skumar on this one... it's very obvious that you use interfaces instead of subclassing. To quote Wiki directly: "This type of adapter uses multiple polymorphic interfaces to achieve its goal. The adapter is created by implementing or inheriting both the interface that is expected and the interface that is pre-existing. It is typical for the expected interface to be created as a pure interface class, especially in languages such as Java that do not support multiple inheritance." – 2rs2ts Jun 26 '13 at 00:08
  • It is a different story if you don't get to choose those interfaces ahead of time, though, I suppose. – 2rs2ts Jun 26 '13 at 00:13
  • +1 for making a turkey act like a duck; clear, concise & comical. –  Jun 02 '14 at 04:59
6

Yes, you can create a class adapter with an interface as long as you're only wrapping a single adaptee. With multiple inheritance you could take two or more adaptees and wrap them into a single interface.

Pace
  • 41,875
  • 13
  • 113
  • 156
5

The full story in heads up is: class adapter pattern is impossible in Java just because Java does not provide multiple inheritance.

In their diagram, they show that the Adapter class subclasses both Target and Adaptee. Your example is (close to) the Object adapter pattern. The difference is that you implement the Target in your adapter class, rather then just subclassing the target (MyNeededInterface in your example)

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • 4
    Yet it achieves the same goal (adapting the adaptee) and clearly isn't the object adapter pattern. If you can't call it the class adapter pattern then what do you call it? – Pace Jun 10 '11 at 13:47
4

GoF (Gang of Four) tells us about two major kinds of adapters:

A. Class adapters. They generally use multiple inheritance to adapt one interface to another. (But we must remember, in java, multiple inheritance through classes is not supported (for a good reason :) ). We need interfaces to implement the concept of multiple inheritance.)

B. Object adapters. They depend on the object compositions.

To illustrate the concepts, I'll present a simple example: (source: book Java Design Patterns)

interface IIntegerValue 
{
    public int getInteger();
}

class IntegerValue implements IIntegerValue
{
    @Override
    public int getInteger() 
    {
        return 5;
    }
}
// Adapter using interface
class ClassAdapter extends IntegerValue
{
    //Incrementing by 2
    public int getInteger()
    {
        return 2 + super.getInteger();
    }
}

// Adapter using composition
class ObjectAdapter implements IIntegerValue
{
    private IIntegerValue myInt;

    public ObjectAdapter(IIntegerValue myInt)
    {
        this.myInt=myInt;
    }

    //Incrementing by 2
    public int getInteger()
    {
        return 2+this.myInt.getInteger();
    }
}

class ClassAndObjectAdapter
{
    public static void main(String args[])
    {
        System.out.println("Class and Object Adapter Demo");
        ClassAdapter ca1=new ClassAdapter();
        System.out.println("Class Adapter is returning :"+ca1.getInteger());
        ClassAdapter ca2=new ClassAdapter();
        ObjectAdapter oa=new ObjectAdapter(new IntegerValue());
        System.out.println("Object Adapter is returning :"+oa.getInteger());
    }
}

Console output:

Class and Object Adapter Demo
Class Adapter is returning :7
Object Adapter is returning :7

Timothy
  • 346
  • 6
  • 18
0

Class Adapters are kind of possible in Java by using single inheritance. As an example from Design pattern for dummies, suppose we have to adapt AWT checkboxes to be used alongside with Swing checkboxes, we can write a class adapter for this.

The UI code in Swing to determine if a check box is checked is done with the isSelected method. But, AWT check boxes dont support isSelected(), they use getState() instead.

So we can write an adapter to wrap an SWT check box and adapt the getState() to isSelected()

  public class CheckboxAdapter extends Checkbox
  { 

      public CheckboxAdapter(String n) 
      {
         super(n);
      }

      public boolean isSelected()
      {
         return getState();
      }
  }

Now we can handle AWT adapted check boxes as we would standard Swing check boxes when it comes to the isSelected method.

  public void itemStateChanged(ItemEvent e)
  {
      String outString = new String("Selected: ");

      for(int loopIndex = 0; loopIndex 
         <= checks.length - 1; loopIndex++){
           if(checks[loopIndex].isSelected()) {
              outString += " checkbox " + loopIndex;
           }
       }
      text.setText(outString);
   }

EDIT: True class adapter are not possible in Java, if they were we could inherit from multiple classes, which we want to mimic in an adapter class.

Also see http://www.journaldev.com/1487/adapter-design-pattern-in-java-example-tutorial for two examples in Java using Class Adapter and Object adapter, to achieve same result.

Saad
  • 915
  • 9
  • 19