JAVA
DESIGN PATTERNS
Structural
Patterns - Adapter Pattern
The
Adapter pattern is used so that two unrelated
interfaces can work together. The joining between
them is called an Adapter. This is something
like we convert interface of one class into
interface expected by the client. We do that
using an Adapter.
Let’s try and understand this with the help
of an example. Again, I will like to take a
general example. We all have electric sockets
in our houses of different sizes and shapes.
I will take an example of a socket of 15 Ampere.
This is a bigger socket and the other one which
is smaller is of 5 Ampere. A 15 Amp plug cannot
fit into a 5 Amp socket. Here, we will use an
Adapter. The adapter can be called a connector
here. The connector connects both of these and
gives output to the client plug which is of
5 Amp.
The Adapter is something like this. It will
be having the plug of suitable for 15 Amp and
a socket suitable for a 5 Amp plug. So, that
the 5 Amp plug which here is the client can
fit in and also the server which here is the
15 Amp socket can give the output.
Let’s try and convert the same example into
a software program. How do we do this? Let’s
try and understand the problem once more. We
have a 5 Amp plug and want a 5 Amp socket so
that it can work. We DO NOT have a 5 Amp socket,
what we have is a 15 Amp socket in which the
5 Amp plug cannot fit. The problem is how to
cater to the client without changing the plug
or socket.
The Adapter Pattern can be implemented in two
ways, by Inheritance and by Composition.
Here is the example of Adapter by Inheritance:
Let’s say there is a socket interface.
Socket.java
package
structural.adapter.inheritance;
/**
* The socket class has a specs for 15 AMP.
*/
public interface Socket { |
|
/**
* This method is used to match the input
to be
* given to the Plug
*
* @return Output of the Plug (Client)
*/
public String getOutput(); |
}//
End of interface |
And there is a class Plug which wants the input
of 5 AMP. This is the client.
Plug.java
package
structural.adapter.inheritance;
/**
* The input for the plug is 5 AMP. which
is a
* mismatch for a 15 AMP socket.
*
* The Plug is the client. We need to cater
to
* the requirements of the Plug.
*/
public class Plug { |
|
private
String specification = "5 AMP";
public String getInput() {
return specification;
}
|
}//
End of class |
Finally, there will be an adapter class. This
will inherit the socket and give output for
Plug.
ConnectorAdapter.java
package
structural.adapter.inheritance;
/**
* ConnectorAdapter has is the connector
between
* the socket and plug so as to make the
interface
* of one system to suit the client.
*/
public class ConnectorAdapter implements
Socket { |
|
/**
* Method coming from the interface
* Socket which we have to make to
* fit the client plug
*
* @return Desired output of 5 AMP
*/
public String getOutput() {
Plug plug = new Plug();
String output = plug.getInput();
return output;
} |
}//
End of class |
This class implements the getOutput() method
of Socket and sets it to fit the client output.
Similarly,
let’s consider the Association and Composition
of objects by which Adapter can be implemented.
The
class Socket gives the 15 AMP output.
Socket.java
package
structural.adapter.composition;
/**
* Class socket giving the 15 AMP output.
*/
public class Socket { |
|
/**
* Output of 15AMP returned.
*
* @return Value of output from socket
*/
public String getOutput() {
return "15 AMP";
} |
}//
End of class |
There
is an interface Plug.java which has a method
getInput(). This is the client and we need to
adapt the output for this input which is 5 AMP.
Plug.java
package
structural.adapter.composition;
/**
* The input for the plug is 5 AMP. which
is a
* mismatch for a 15 AMP socket.
*
* The Plug is the client. We need to cater
to
* the requirements of the Plug.
*/
public interface Plug { |
|
public String getInput(); |
}//
End of class |
Plug5AMP
is the implementation of Plug which requires
5 AMP of input.
Plug5AMP.java
package
structural.adapter.composition;
public class Plug5AMP implements Plug {
|
|
/**
* Get the input of client i.e. Plug
*
* @return 5 AMP
*/
public String getInput() {
return "5 AMP";
} |
}//
End of class |
The
Adapter here takes output from the Socket. If
the output is what is needed, it gives it to
the Plug else, it overrides the value and returns
the adapter output.
ConnectorAdapter.java
package
structural.adapter.composition;
/**
* Using composition
*/
public class ConnectorAdapter { |
|
Plug5AMP plug5;
public ConnectorAdapter(Plug5AMP plug)
{
this.plug5 = plug;
}
public static void main(String[] args)
{
// Taking output from the Socket
Socket socket = new Socket();
String outputFromSocket = socket.getOutput();
// Giving away input to the Plug
ConnectorAdapter adapter = new ConnectorAdapter(new
Plug5AMP());
String inputToPlug = adapter.getAdapterOutput(outputFromSocket);
System.out.println("New output by
adapter is: "+inputToPlug);
}
public String getAdapterOutput(String
outputFromScoket) {
/*
* if output is same, return
*/
if (outputFromScoket.equals(plug5.getInput()))
{
return outputFromScoket;
}
/*
* Else, override the value by adapterOutput
*/
else {
String adapterOutput = plug5.getInput();
return adapterOutput;
}
|
}//
End of class |
This
is how the Adapter pattern works. When one interface
cannot be changed and has to be suited to the
again cannot-be-changed client, an adapter is
used so that both the interfaces can work together.
|