Thursday, 22 November 2007

Java BuiltIn Adapter classes Really follow Adapter Pattern?

First let us start introducing about this pattern officially.

According to WikiPedia:
Adpater Pattern converts the interface of a class into a one that a client is expecting.Hence it allows classes to work together that normally would not have been possible due to incompatible interfaces.

Note that Adapter pattern is also known as Wrapper.

Motivation:

-> Sometimes a toolkit or class library can not be used because its interface is incompatible with the interface requried by the application.

-> Probably we may not change the library interface,since we may not change the source code.

Usage:

-> We need to use an existing class and its interface doesnot match the one we need.

There are 2 types of Adpater Pattern:

Object Adapter Pattern:
In this type of pattern adapter contains an instance of the class it wraps.Hence it makes calls to the instance of the wrapped object.One imp we need to realize that Adapter hides the Adaptee interface from the client.

Class Adapter Pattern:
This type of adapter uses multiple inheritance to achieve its goal.The adapter is created from both the interface that is expected and the interface that is pre-existing.Also as known if there are more adaptees then we may not use multiple adaptees.Hence this pattern may not be used in java and other languages which support multiple inheritance.

The classic round peg and square pegs example:

// Target class


public class SquarePeg {
public void insert(String str) {
System.out.println("Square peg insert()" + str);
}
}


// Adaptee Class


public class RoundPeg {

public void insertIntoHole(String msg) {
System.out.println("Round peg insertIntoHole():" + msg);
}
}


If a client only understands the SquarePeg interface for inserting pegs the insert() method,how can it insert round pegs? So a peg adapter.

/*
* Adapter Class.
* It adapts a RoundPeg to a SquarePeg
* It's interface is that of a SquarePeg
*/



public class PegAdapter extends SquarePeg {

private RoundPeg roundPeg;

public PegAdapter(RoundPeg peg) { this.roundPeg=peg; }

public void insert(String str) { roundPeg.insertIntoHole(str); }

}



Finally testing our client..


public class TestPegs {

public static void main(String[] args) {

RoundPeg roundPeg=new RoundPeg();
SquarePeg squarePeg=new SquarePeg();

squarePeg.insert("Inserting square peg");

// Using Our Adapter

PegAdapter pegAdapter=new PegAdapter(roundPeg);
pegAdapter.insert("Inserting round peg...");
}
}




Adapter pattern indeed in used in many places in java.

For example java.awt.WindowAdapter class is provided which tries to decrease the burden to us by implementing few common methods from WindowListener,WindowStateListener and WindowFocusListener interfaces if must provide the default implementation of these methods every time we implement from these interfaces.Hence adapter decreases the pain to some extent in this case.

Below example shows one implementation of builtin Adapter Pattern in java.


package output;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

public class WindowAdapterTest {
public static void main(String args[]) {
JFrame frame = new JFrame("Window Listener");
WindowListener listener = new WindowAdapter() {
public void windowClosing(WindowEvent w) {
System.exit(0);
}
};
frame.addWindowListener(listener);
frame.setSize(300, 300);
frame.show();
}
}


However i have strong feeling that still WindowAdapter class alone is not a 100% adapter if we must strictly follow below definition

What definition says?
"Adpater Pattern converts the interface of a class into a one that a client is expecting.Hence it allows classes to work together that normally would not have been possible due to incompatible interfaces." .

Of course we may say pointing to the above example....
JFrame objects expect to be able to invoke the windowClosing() method on their associated WindowListener objects. But the WindowAdapterTest class does not have this method! It really wants the frame to invoke exit() method in System class when windowClosing event is fired. The anonymous inner class we instantiated acts as an adapter object, adapting System to WindowListener!

But still somehow not convinced for the above example?????

May i request any one comment on this?

I know i may be wrong but better to know @somepoint_of_time in life than @never.

1 comment:

Anonymous said...

you are a good copy cat