Adapter
Template:Computer Science Design Patterns/Topics
Used to change the interface of one class to another. It is also called a wrapper class.
Example - Object Adapter
Implementation in Ruby
Ruby
class Adaptee def specific_request # do something end end class Adapter def initialize(adaptee) @adaptee = adaptee end def request @adaptee.specific_request end end client = Adapter.new(Adaptee.new) client.request
Implementation in Python
class Adaptee: def specific_request(self): return 'Adaptee' class Adapter: def __init__(self, adaptee): self.adaptee = adaptee def request(self): return self.adaptee.specific_request() client = Adapter(Adaptee()) print client.request()
Implementation in Java
Before
Because the interface between Line and Rectangle objects is incompatible, the user has to recover the type of each shape and manually supply the correct arguments.
class LegacyLine { public void draw(int x1, int y1, int x2, int y2) { System.out.println("line from (" + x1 + ',' + y1 + ") to (" + x2 + ',' + y2 + ')'); } }
class LegacyRectangle { public void draw(int x, int y, int w, int h) { System.out.println("rectangle at (" + x + ',' + y + ") with width " + w + " and height " + h); } }
public class AdapterDemo { public static void main(String[] args) { Object[] shapes = { new LegacyLine(), new LegacyRectangle() }; // A begin and end point from a graphical editor int x1 = 10, y1 = 20; int x2 = 30, y2 = 60; for (Object obj : shapes) { if (obj instanceof LegacyLine) { ((LegacyLine)obj).draw(x1, y1, x2, y2); } else if (obj instanceof LegacyRectangle) { ((LegacyRectangle)obj).draw(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1)); } } } } // Line from (10,20) to (30,60) // Rectangle at (10,20) with width 20 and height 40
After
The Adapter’s “extra level of indirection” takes care of mapping a user-friendly common interface to legacy-specific peculiar interfaces.
class LegacyLine { public void draw(int x1, int y1, int x2, int y2) { System.out.println("line from (" + x1 + ',' + y1 + ") to (" + x2 + ',' + y2 + ')'); } }
class LegacyRectangle { public void draw(int x, int y, int w, int h) { System.out.println("rectangle at (" + x + ',' + y + ") with width " + w + " and height " + h); } }
interface Shape { void draw(int x1, int y1, int x2, int y2); }
class Line implements Shape { private LegacyLine adaptee = new LegacyLine(); public void draw(int x1, int y1, int x2, int y2) { adaptee.draw(x1, y1, x2, y2); } }
class Rectangle implements Shape { private LegacyRectangle adaptee = new LegacyRectangle(); public void draw(int x1, int y1, int x2, int y2) { adaptee.draw( Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1) ); } }
public class AdapterDemo { public static void main(String[] args) { Shape[] shapes = {new Line(), new Rectangle()}; // A begin and end point from a graphical editor int x1 = 10, y1 = 20; int x2 = 30, y2 = 60; for (Shape shape : shapes) { shape.draw(x1, y1, x2, y2); } } } // Line from (10, 20) to (30, 60) // Rectangle at (10, 20) with width 20 and height 40
Example - Class Adapter
Implementation in Python
class Adaptee1: def __init__(self, *args, **kw): pass def specific_request(self): return 'Adaptee1' class Adaptee2: def __init__(self, *args, **kw): pass def specific_request(self): return 'Adaptee2' class Adapter(Adaptee1, Adaptee2): def __init__(self, *args, **kw): Adaptee1.__init__(self, *args, **kw) Adaptee2.__init__(self, *args, **kw) def request(self): return Adaptee1.specific_request(self), Adaptee2.specific_request(self) client = Adapter() print client.request()