Download as pdf or txt
Download as pdf or txt
You are on page 1of 19

Adapter Pattern

Or building a wrapper class


Adapter Purpose
Purpose: Create a wrapper around an
existing class that you dont control.
The wrapper makes the object conform
to your needs.

Problem (or When to Use): Have a


class that almost does what I need.
Has all (or almost) the right behavior, but has
wrong access methods.
Adapter Pattern Solution
Solution: Build a wrapper class.

Implementation: Build a wrapper class


around the existing class. Use your class
instead.

Consequences: Allows pre-existing classes


to be used in your code. Will not work if
existing class is missing some key behavior.
So Whats a Wrapper?
A class that encompasses another class
(or method, or)

Weve seen examples with the


composition notation.
Why would this indicate that one class wraps
around another?
Barn WoodPlank
Java Example: Integer
Example : The Integer class in Java.
This class wraps itself around the int
datatype.
So not quite like composition, but close.

Why did Java developers want to do this?


int does everything they want, except cannot be
treated as an object.
Solution: Integer class wraps int, and now extends
Object class. So the Integer has the int and is an
Object.
Object Integer
Java Example: Integer (cont.)
Whats the advantage of this wrapper?
Some methods can require an Object as a parameter.
e.g., void toString(Object o)
e.g., boolean equals(Object o)
(actually a method in the Object class)
Can accept almost anything!

But cant accept an int (or char, or float, or double, or


boolean).

Problem: cant pass int as an Object.


Solution: build wrapper called Integer.
This is an adapter class!
Java Example: Integer (cont.)
What would the code look like? (pseudo)
public class Integer
{
private int i; //creates an int inside this class.
//This is what we are wrapping around!
public Integer(int iValue)
{
i = iValue; //sets the ints value when instantiated
}

public int getInteger() //actually called intValue()


{
return i;
}

public String toString()


{
return +i;
}
}
Java Example: Integer (cont.)
So now when a method requires an
Object, we can pass it the integer
rather than the int.

toString(3) //ERROR
toString(Integer(3)) //Ahhhhh wrapped!
Another Example:
EmailSender
Spose I am asked to write an email sender.

Suppose project already has an existing class


SpamSender()
existing class has methods for
sendSpam
setSubject
setBody

Suppose that the sendSpamTo must be given multiple


addresses
Another Example (cont.)
1. Id prefer my code was written with a
method called sendEmail() rather than
sendSpam()
2. My code only provides one email address.
3. sendSpam() returns the # of bad email
addresses, but I dont care about that.
4. But, I dont want to rewrite everything!

Solution: A wrapper Adapter pattern


Why not solve with a Faade? Because we are
changing the behavior, not just hiding existing
behaviors.
Another Example (cont.)
public class EmailSender
{
private EmailAddress fakeAddress = new EmailAddress(blubber@blubber.com);
private SpamSender spam;

public EmailSender()
{
spam = new SpamSender(); //creates a SpamSender inside this class.
} //This is what we are wrapping around!

public void sendEmail(EmailAddress sendToRealAddress)


{
spam.sendSpam(sendToRealAddress, fakeAddress);
}
}
I dont have two addresses,
so I just give it a fake one.
Another Example (cont.)
So whats the UML picture?

EmailSender
+sendEmail(:EmailAddress):void

SpamSender
+sendSpam(:EmailAddress, :EmailAddress):int
Another Example (cont.)
Collaboration diagram

:Driver

1: sendEmail(:EmailAddress) : void

:EmailSender

1.1: sendSpam(:EmailAddress, :EmailAddress) : int

:SpamSender
Adapter Pattern UML
UML diagram:

Adapter Adaptee
Now can use Adapter in
place of Adaptee.
Adapter Pattern UML May Vary
As Ill say many times, design patterns may
be (slightly) altered to fit your needs.
Theyre just patterns.

Consider the following:


Before the Adapter Pattern

Client ExistingClass Adaptee


+methodCall() +adapteeCall()

Almost does what we want,


but not quite.
Adapter Pattern UML Option 2
Common alteration of Adapter:
Use this when Client, ExistingClass,
and Adaptee already exist.
Adapter takes the interface of
Client ExistingClass Adaptee and makes it work with
+methodCall() the ExistingClass. So client calls
methodCall and gets behavior of
adapteeCall.
Whats the advantage of this
approach? The Client class never
even knows that the wrapper class Adapter Adaptee
exists. Taking advantage of
+methodCall() +adapteeCall()
polymorphism! Same method call,
different behavior because deals with
Adaptee.
Adapter UML: Why Not
Inheritance?
Well, it might be, (as above UML shows) but not
usually.
We want to adapt something to our own purposes and hide
the old inappropriate version.
For example, we want to hide the SpamSender and replace it
with an EmailSender.

Inheritance will extend existing code, but may not hide the old
code.
If EmailSender inherits from the SpamSender, then the
interface will include the inherited method sendSpam.
Aurgh! We wanted to get rid of that, or hide it.
We could override the sendSpam, but then we have an
interface with a misleading method name (sendSpam) that
doesnt sound anything like sendEmail.
Better option: Use composition to completely hide the old
code.
How Different From Faade?
Very similar dealing with an interface to pre-existing classes.

Adapter provides an interface without simplifying.


Adds new features or a new way to access old features.
polymorphism likely
composition likely (almost always)
aggregation not likely

Faade provides simplified interface.


Never adds new features.
polymorphism less likely
composition likely
aggregation also likely

Sometimes, the adaptation might appear to simplify. In those


cases, you are creating both an adapter and a faade.
OK, Your Turn
Create 2 teams.

Each team must adapt the Java LinkedList


API to be a Stack.
In other words, turn the existing linked list into a stack.

If unclear, justify why it is not just the faade


pattern.

If stuck, consider other teams answer.

You might also like