Adapter Pattern
Also known as Wrapper.Definition
The Adapter pattern is used to translate the interface of one class into another interface. This means that we can make classes work together that couldn't otherwise because of incompatible interfaces. A class adapter uses multiple inheritance (by extending one class and/or implementing one ormore classes) to adapt one interface to another. An object adapter relies on object aggregation.
Where to use
•When you want to use an existing class, and its interface does not match the one you need.•When you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces.
•When you want to increase transparency of classes.
•When you want to make a pluggable kit.
Benefits
•Highly class reusable.•Introduces only one object
Drawbacks/consequences
When using Java, Target must be an interface.Adapter Pattern - Class Diagram
In the class-diagram above:
•A Client class expects a certain interface (called the Target interface)
•An available interface doesn't match the Target interface
•An Adapter class bridges the gap between the Target interface and the available interface
•The available interface is called the Adaptee
Adapter Pattern Example
public interface FileManager { public String open(String s); public String close(); public String read(int pos, int amount, byte[] data); public String write(int pos, int amount, byte[] data); } import java.util.*; import java.io.*; public class FileManagerUtil { private RandomAccessFile f; public boolean openFile(String fileName) { System.out.println("Opening file: "+fileName); boolean success=true; return success; } public boolean closeFile() { System.out.println("Closing file"); boolean success=true; return success; } public boolean writeToFile(String d, long pos, long amount) { System.out.print("Writing "+amount+ " chars from string: "+d); System.out.println(" to pos: "+pos+" in file"); boolean success=true; return success; } public String readFromFile(long pos, long amount) { System.out.print("Reading "+amount+ " chars from pos: "+pos+" in file"); return new String("dynamite"); } } public class FileManagerImpl extends FileManagerUtil implements FileManager { public String close() { return new Boolean(closeFile()).toString(); } public String open(String s) { return new Boolean(openFile(s)).toString(); } public String read(int pos, int amount, byte[] data) { return readFromFile(pos, amount); } public String write(int pos, int amount, byte[] data) { boolean tmp= writeToFile(new String(data), pos, amount); return String.valueOf(tmp); } } public class FileManagerClient { public static void main(String[] args) { FileManager f = null; String dummyData = "dynamite"; f = new FileManagerImpl(); System.out.println("Using filemanager: "+ f.getClass().toString()); f.open("dummyfile.dat"); f.write(0, dummyData.length(), dummyData.getBytes()); String test = f.read(0,dummyData.length(), dummyData.getBytes()); System.out.println("Data written and read: "+test); f.close(); } }Imagine you need to develop a simple file manager to handle text documents. There is an existing resource that already handles this, but by some reason you are forced to a specific interface for your file manager. By using a class adapter we can use the forced interface and still reuse the existing functionality. In the class diagram below the interface FileManager is the target (desired interface). FileManagerUtil is the existing utility class that we would like to adapt to FileManager interface. We do the actual adaptation in the class FileManagerImpl, this class uses the desired interface and the
existing functionality through inheritance, i.e. a class adapter.
When FileManagerClient is executed the result is:
c:>Opening file: dummyfile.dat
c:>Writing 8 chars from string: dynamite to pos: 0 in file
c:>Reading 8 chars from pos: 0 in fileData written and read: dynamite
c:>Closing file
0 comments:
Post a Comment