Wikipedia defines the Adapter Pattern as:
In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.
Let’s see this in action. Let’s suppose we are building a Duck simulator.
interface Duck {
quack();
fly();
}
We have a Duck interface which consists of two methods.
class MallardDuck implements Duck {
display() {
// displays mallard duck
}
fly() {
// implement swim behaviour
}
quack() {
// implements quack behaviour
}
}
We have MallardDuck
which implements the Duck
interface.
class DuckSimulator {
constructor() {
const duck = new MallardDuck();
this.quackAndFly(duck);
}
quackAndFly(duck: Duck) {
duck.quack();
duck.fly();
}
}
Inside the DuckSimulator
we create a new Duck
instance of MallardDuck
and assign it to the duck
. So far everything is working fine. If we call the quackAndFly
method of the DuckSimulator
it will execute the fly
and quack
method of MallardDuck
Now let’s suppose we want to add Turkey
into our DuckSimulator
.
interface Turkey {
gobble();
fly();
}
The Turkey
interface is slightly different from the Duck
’s interface so we can not add it directly to our DuckSimulator
.
class WildTurkey implements Turkey {
gobble() {
console.log("gobble!");
}
fly() {
console.log("Fly");
}
}
We can not use Turkey
in DuckSimulator
because DuckSimulator
expects the type objects to be of type Duck
and the interface for Duck
and Turkey
have differences due to which it can not be used.
To overcome this we can use an Adapter
. An Adapter
acts as a bridge between Duck
and Turkey
objects.
We will create a new class called TurkeyAdapter
. This class will act as an adapter between Duck
and Turkey
.
This class will implement the Duck
interface so we can directly plug it into the Duck
class. Inside the implementation of Duck
class TurkeyAdapter implements Duck {
constructor(private turkey: Turkey) {}
quack() {
this.turkey.gobble();
}
fly() {
this.turkey.fly();
}
}
Now we can use this inside the DuckSimulator
class DuckSimulator {
constructor() {
const duck = new MallardDuck();
this.quackAndFly(duck);
const wildTurkey = new TurkeyAdapter(new WildTurkey());
this.quackAndFly(wildTurkey);
}
quackAndFly(duck: Duck) {
duck.quack();
duck.fly();
}
}