Profile & Notion,
To make the interface of one Object look like something else they're not.
In Real World, For the AC Power example.
How 2 plugs AC Power adaptes with 3 plugs... Let' adaptive, change the interface of the 2 plugs AC PW look like the plugs 3.
The Adapter Pattern - it converts the interface of a class into another interface the client expecet. Adapters let's classes work together that couldn't otherwise because of incompatible interfaces.
Realistic in practise,
Problem
You got an exsiting software system that you need to work a new vendor class library into, but the interface different each other.
Resolving
Okay, now you don't want to change your exsiting stable code and also you cannot change the code of the vendor.
So what do you do? Well, you can write a class (adaptor) that adapts the new vendor interface into the one's your expecting.
The adapter acts as the middleman by receiving requests from the client and converting them into to the vendor class.
Adapter in Action
Example 1:
Todo: Make a Turkey like a Duck
Duck Interface
//Our Ducks implement a Duck interface that allows Ducks to quack and fly Public interface Duck { public void quack(); public void fly(); }
A Mallard Duck
public class MallardDuck implements Duck{ public void quack() { System.out.println("Quack!"); } public void fly(){ System.out.println("I'm flying!"); } }
The Interface of TurKey
public interface Turkey{ public void gobble(); // Turkeys doesn't quack, they gobble public void fly(); // They can fly, but they can only fly short distance }
A Wild Turkey
public class WildTurkey implements Turkey { public void gobble(){ System.out.println("Gobble gobble"); } public void fly(){ System.out.println("I'm flying a short distance"); } }
Now, how to make a Turkey like a duck. Let's write a Adapter.
public class TurkeyAdapter implements Duck { Turkey turkey; public TurkeyAdapter(Turkey turkey){ this.turkey = turkey; } public void quack() { turkey.gobble(); } public void fly() { //hehe, we want to make a Turkey like a Duck, so make it fly more than one times. turkey.fly(); turkey.fly(); turkey.fly(); } }
So, now let's test a duck protended by a Turkey.
public void main(String[] args){ WildTurkey turkey = new WildTurkey(); Duck turkeyAdapter = new TurkeyAdapter(turkey); System.out.println("The wild Turkey acts ....."); turkey.gobble(); turkey.fly(); System.out.println("The duck protended by wild Turkey acts ..." duckAct(turkeyAdapter); } public void duckAct(Duck duck){ duck.quack(); duck.fly(); } // The message printed belows // The wild Turkey acts..... // Gobble, gobble // I'm flying a short distance. // The duck protended by wild Turkey acts ... // Gobble, gobble // I'm flying a short distance // I'm flying a short distance // I'm flying a short distance
Turkey_Duck_Comsuption
Example 2:
Todo: Adapting an Enumeration to an Iterator
Design
Remove() adapt issue,
Enumeration doesn't support remove. so there is no way for us to implement a fully fuctioning remove() method on the adapter. so UnsupportedOperationException will throw.
This case where the adapter isn't perfect; but as long as the well documented make this is a reasonable solution.
public class EnumerationIterator implements Iterator { Enumeration em; public EnumerationIterator(Enumeration em){ this.em = em; } public boolean hasNext() { return em.hasMoreElements(); } public Object next() { return em.nextElement(); } public void remove() { new UnsupportedOperationException(); } }
Check how it works
public class EnumerationIteratorTest { static Vector<String> vs ; static{ vs = new Vector<String>(); vs.add("a"); vs.add("b"); } @Test public void testFuctional(){ Enumeration<String> e = vs.elements(); @SuppressWarnings("unchecked") Iterator<String> i = new EnumerationIterator(e); while( i.hasNext() ){ assertTrue( "ab".indexOf( i.next() ) >= 0 ); } } }