Card 03/ 08
Adapter Template in Python, Java and TypeScript
One Target interface, one Adaptee with the wrong method, and an Adapter that translates the call.
The Adapter template is the pattern in its pure form, with the participant names from the class diagram. The adaptee returns its text reversed, so the adapter has a real translation to make rather than a rename. The steps add each participant in Python, and the tabs give the complete program in three languages, each with its output.
Building the template one participant at a time
Target
The interface the client already expects.
class Target(ABC):
@abstractmethod
def request(self) -> str: ...Adaptee
An existing class with useful behaviour under another name and in another form.
class Adaptee:
def specific_request(self) -> str:
return ".eetpadA eht fo ruoivaheb lufesU"Adapter
Implements the target, holds the adaptee, and translates each call.
class Adapter(Target):
def __init__(self, adaptee: Adaptee) -> None:
self._adaptee = adaptee
def request(self) -> str:
return self._adaptee.specific_request()[::-1]Client
Written against the target alone, it is given the adapter.
def client(target: Target) -> None:
print(target.request())
client(Adapter(Adaptee()))The complete template
from abc import ABC, abstractmethod
class Target(ABC):
@abstractmethod
def request(self) -> str: ...
class Adaptee:
def specific_request(self) -> str:
return ".eetpadA eht fo ruoivaheb lufesU"
class Adapter(Target):
def __init__(self, adaptee: Adaptee) -> None:
self._adaptee = adaptee
def request(self) -> str:
return self._adaptee.specific_request()[::-1]
def client(target: Target) -> None:
print(target.request())
client(Adapter(Adaptee()))Useful behaviour of the Adaptee.public class AdTemplate {
static void client(Target target) {
System.out.println(target.request());
}
public static void main(String[] args) {
client(new Adapter(new Adaptee()));
}
}
interface Target {
String request();
}
class Adaptee {
String specificRequest() {
return ".eetpadA eht fo ruoivaheb lufesU";
}
}
class Adapter implements Target {
private final Adaptee adaptee;
Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public String request() {
return new StringBuilder(adaptee.specificRequest()).reverse().toString();
}
}Useful behaviour of the Adaptee.interface Target {
request(): string;
}
class Adaptee {
specificRequest(): string {
return ".eetpadA eht fo ruoivaheb lufesU";
}
}
class Adapter implements Target {
constructor(private readonly adaptee: Adaptee) {}
request(): string {
return this.adaptee.specificRequest().split("").reverse().join("");
}
}
function client(target: Target): void {
console.log(target.request());
}
client(new Adapter(new Adaptee()));Useful behaviour of the Adaptee.In all three the client calls request() and prints a readable sentence, never learning that the text came from specific_request() backwards. The adaptee is untouched: nothing in it knows the target exists, so the pattern works even when the adaptee is a library you cannot edit.
← → move through sections and cards