When I used to live in France and travel in the US, I had an adapter for my phone charger since the electrical outlets are different: shape, voltage, etc. The Adapter Pattern does the same. It aims to wrap an existing interface to conform it to a required interface.
Let’s consider this company with a CEO, a manager (the “adapter”) and a programmer:
interface CEO { // implementations: bossyCEO, micromanagerCEO, etc. 🙂
public Demand command();
}
interface Programmer { // implementations: rebelliousProgrammer, etc.
public void execute(Expectation cmd);
}
interface Manager { // implementations: terrorizedManager, angryManager, etc.
public void hear(Demand demand);
public void execute();
}
// adapter class
class SmartManager implements Manager {
private Programmer programmer; // would not be private if CEO is micromanaging 🙂
private Project project;
public SmartManager(Programmer programmer) { // only one programmer 🙂
this.programmer = programmer;
}
public void hear(Demand demand) {
decrypt(demand);
discuss(programmer, demand);
project = plan(demand);
}
public void execute() {
Expectation expectation = project.getPlan();
programmer.execute(expectation);
}
}
The adapter usually wraps the interface it adapts to transform the calls from the consumer interface.
This pattern may require the creation of temporary objects to handle the “adaptation” which impacts performance (time and resources). If it is the case, caching those temporary objects will help.
In our illustration, Project is a temporary object which was created by the plan(Demand demand) method. We could cache project if the CEO has the same demand.
private Map<Demand, Project> plans;
private Project plan(Demand demand) {
project = plans.get(demand);
if (project == null) {
project = ... // create a new project
plans.add(demand, project); // cache
}
return project;
}