Creational Pattern — Adapter
Simply put, the Adapter pattern allows two incompatible piece to work together. This is done by creating an adapter to convert one of the pieces’ interface to be acceptable by another.
- Client : calls the Adapter to talk to Adaptee
- Adapter : twist the Adaptee’s interface to make it acceptable by the Client
- Adaptee : does nothing, simply has its interface to be twisted by Adapter.
This allows for loose coupling as the two otherwise incompatible pieces can separate from each other, and it’s down to the adapter to create the communication channel. Most likely, you have been using adapter already, like when you integrate a 3rd party API into the existing infrastructure.
Note that to keep the adapter light and easy to maintain, you should only put connection logic in it but not business logic.
Let’s look at a python implementation first:
import abc
class BreadAdapterInterface(metaclass=abc.ABCMeta):
def __init__(self):
pass
@abc.abstractmethod
def labelBread(self, **args):
pass
@abc.abstractmethod
def chooseFlour(self, **args):
pass
@abc.abstractmethod
def waitForBake(self, **args):
pass
class BreadAdaptee():
def __init__(self, kind=None, flour_kind="white",
rise_in_min=0, bake_in_min=0, temp=200):
self.kind = kind
self.flour_kind = flour_kind
self.rise_in_min = rise_in_min
self.bake_in_min = bake_in_min
self.temp = temp
def label_bread(self, kind):
self.kind = kind
def choose_flour(self, flour_kind):
self.flour_kind = flour_kind
def wait_for_bake(self, bake_in_min, temp):
self.bake_in_min = bake_in_min
self.temp = temp
class BreadAdapter(BreadAdapterInterface):
__bread = None
def __init__(self, bread=BreadAdaptee()):
self.__bread = bread
def labelBread(self, **args):
return self.__bread.label_bread(args)
def chooseFlour(self, **args):
return self.__bread.choose_flour(args)
def waitForBake(self, **args):
return self.__bread.wait_for_bake(args)
breadAdapter = BreadAdapter()
breadAdapter.chooseFlour("Wholemeal")
Now another one for JavaScript:
class BreadAdaptee {
constructor(
kind = None,
flour_kind = "white",
rise_in_min = 0,
bake_in_min = 0,
temp = 200
) {
this.kind = kind;
this.flour_kind = flour_kind;
this.rise_in_min = rise_in_min;
this.bake_in_min = bake_in_min;
this.temp = temp;
}
label_bread(kind) {
this.kind = kind;
}
choose_flour(flour_kind) {
this.flour_kind = flour_kind;
}
wait_for_bake(bake_in_min, temp) {
this.bake_in_min = bake_in_min;
this.temp = temp;
}
}
class BreadAdapter {
constructor() {
this.bread = new BreadAdaptee();
}
operation(operation, ...args) {
switch (operation) {
case "labelBread":
return this.bread.label_bread(args);
case "chooseFlour":
return this.bread.choose_flour(args);
case "waitForBake":
return this.bread.wait_for_bake(args);
default:
return undefined;
}
}
}
//Client call:
const breadAdapter = new BreadAdapter();
breadAdapter.operation("chooseFlour", "wholemeal");
That’s so much of it! Happy Reading!