Convert the interface of a class into another interface client expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
- You've got an existing software system. The interface of the new vendor class you need to work with doesn't match with your existing code.
- Changing the existing code is expensive or will affect the other working functionalities.
Write a Adapter
class that adapts the new vendor interface into the one you're expecting. The adapter acts as the middleman by receiving requests from the client and converting them into requests that make sense on the vendor class.
There are two variations, namely Object Adapter and Class Adapter.
- Target (Duck)
- defines the domain-specific interface that client uses.
- Adapter (TurkeyClassAdapter, TurkeyObjectAdapter)
- adapts the interface Adaptee to the Target interface.
- Adaptee (Turkey)
- defines an existing interface that needs adapting.
- Client
- collaborates with objects conforming to the Target interface.
[Source: http://www.dofactory.com/net/adapter-design-pattern]
Clients call operations on an Adapter instance. In turn, the adapter callas Adaptee operations that carry out the request.
Benefits
- It allows more flexibility in design
- They handle logic by wrapping a new interface around that of an exisiting class so you can use new APIs and avoid breaking existing implementations.
- It absolutely interconnects two incompatible interfaces.
Drawbacks
- Sometimes many adaptations are required along an adapter chain to reach the required type.
Benefits
- Adapts only the required methods of the existing class and leave the others unchanged.
- No additional object is required.
Drawbacks
- The whole interface of the existing class is visible
- Not able to adapt all the subclasses of the existing class at one go. You have to define explicitely which (sub-)class you adapt.
Benefits
- Subclasses of the existing class can also be adapted easily.
Drawbacks
- Every required method of the existing class should be redefined in Adapter class. It unnecessarily increases the size of code, because a lot of code is needlessly duplicated.
- Additional object is required.
Target (Duck)
// Target
public interface IDuck
{
void Quack();
void Fly();
}
Adaptee (Turkey)
public interface ITurkey
{
// Turckeys don't quack, they gobble
void Gobble();
void Fly();
}
public class WildTurkey : ITurkey
{
public void Gobble()
{
Console.WriteLine("Gobble gobble");
}
public void Fly()
{
Console.WriteLine("Flying short distance");
}
}
Class Adapter
class TurkeyClassAdapter : WildTurkey, IDuck
{
public void Quack()
{
base.Gobble();
}
void IDuck.Fly()
{
for (int i = 0; i < 5; i++)
{
base.Fly();
}
}
}
Object Adapter
public class TurkeyObjectAdapter : IDuck
{
private readonly ITurkey _turkey;
public TurkeyObjectAdapter(ITurkey turkey)
{
this._turkey = turkey;
}
public void Quack()
{
_turkey.Gobble();
}
public void Fly()
{
for (int i = 0; i < 5; i++)
{
_turkey.Fly();
}
}
}
Client
public static void Run()
{
// Class Adapter
TurkeyClassAdapter classAdapter = new TurkeyClassAdapter();
testDuck(classAdapter);
// Object Adapter
WildTurkey turkey = new WildTurkey();
TurkeyObjectAdapter objectAdapter = new TurkeyObjectAdapter(turkey);
testDuck(objectAdapter);
}
// Client expects duck interface only
static void testDuck(IDuck duck)
{
duck.Quack();
duck.Fly();
}
-
Bridge has a structure similar to an object adapter, but Bridge has a different intent. It is meant to separate an interface from its implementation so that they can be variaed easily and independently. An adapter is meant to change the interface of an existing object.
-
Decorator enhances another object without changing its interface. A decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn't possible with pure adapters.
-
Proxy defines a representative or surrogate for another object and does not change its interface.