Implementing Class Adapter Pattern in Java

18,097

Solution 1

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.

Solution 2

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.

Solution 3

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)

Solution 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

Share:
18,097
markjason72
Author by

markjason72

I am a java programmer working with python at times.I like using Django for making webapps.I have used postgresql for most of my projects..

Updated on June 04, 2022

Comments

  • markjason72
    markjason72 over 1 year

    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?

  • Vineet Reynolds
    Vineet Reynolds over 12 years
    This is the object adapter pattern. The OP wants to attempt implementing the class adapter pattern.
  • Kevin
    Kevin over 12 years
    @Vineet: Could you expand? I'm not sure what the difference is between both? I thought there was just one general 'adapter pattern'.
  • Vineet Reynolds
    Vineet Reynolds over 12 years
    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 for instance.
  • Kevin
    Kevin over 12 years
    @Vineet: Ah I see, thanks for the link. The adapter pattern through inheritance would be impossible in Java though.
  • Pace
    Pace over 12 years
    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?
  • rai.skumar
    rai.skumar over 10 years
    don't agree that Class Adapter is not possible; check out this link en.wikipedia.org/wiki/Adapter_pattern
  • 2rs2ts
    2rs2ts over 10 years
    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
    2rs2ts over 10 years
    It is a different story if you don't get to choose those interfaces ahead of time, though, I suppose.
  • Admin
    Admin over 9 years
    +1 for making a turkey act like a duck; clear, concise & comical.