Adapter Pattern: Travel around the world as Pro Tennis Player

I'm an enthusiastic Chilean software engineer in New Zeland. I mostly focus on the back-end of the systems. This is my site, Señor Developer, where I share my knowledge and experience.
Search for a command to run...

I'm an enthusiastic Chilean software engineer in New Zeland. I mostly focus on the back-end of the systems. This is my site, Señor Developer, where I share my knowledge and experience.
In this series, I will show you a set of Object Oriented Design Patterns which provides ways to solve common problems in software design.
In this article I will explain one Object Oriented Programing Pattern called the "Decorators Pattern" and how we can implement it using typescript to handle multiple-optional behaviors. Lets imagine that we have an ice-cream shop which offers to our ...
Quilla Frontend Kit turns recurring API, authentication, and server-state concerns into composable TypeScript packages.

Quilla Backend Kit provides the foundations for structured TypeScript services while leaving the application architecture in your hands.

Practical constraints for preserving the framework’s boundaries, dependency direction, and readability as a test suite grows.

A tool-agnostic approach to separating test intent from UI mechanics as an automation suite grows.

In this article, we will go through the entire process of set up Visual Studio Code for debugging “Deno” programs using “V8 Inspector Protocol”. Step-by-step, we will be learning how to configure VSCode to debug a Deno project. If you don’t know Deno...

Imagine you are a professional tennis player who travel around the world for important tournaments but you are not able to speak any language other than English... So, in every non-english country you need someone to helps you with the speech. You might need to hire a professional interpreter to adapt your speech into the fan's country...
Given the above context, let's have a look at the definition of the Adapter Pattern:
"Adapter pattern allows objects with incompatible interfaces to work together".
And also, here is the Adapter Pattern class diagram:

Client: The component which is implemented against the target interface.
Target: The expected interface that the client invokes method on.
Adapter: The code that allows implement the interface that the client implements which has the ability to "talk" with the "adaptee" class.
Adaptee: is the library, component or system that we are not able to change.
Backing to the Profesional Tennis Player example; We have a player who is an english speaker and fans around the world (non-english speaker). As the player's fans doesn't speak english and we can not change the way that fans speaks we will use a "profesional interpreter" to translate the player's speech into the fan's language rather than learn every single language.
Before writing the code, let's look at the class diagram:

Greetings: A polite word or sign of welcome
TennisPlayer: Is the client who uses an english interface to say hello
SpanisInterpreterAdapter: Is the interpreter who can understand english and also, speak Spanish.
Spanish: Thats represent the language of the player's fans
The IGreetings interface represents the "Target" node of the Adapter Pattern diagram. We have a simple interface with one method to say hello:
export interface IGreetings {
sayHello: () => void;
}
The SpanishInterpreterAdapter class represents the "Adapter" node of the Adapter Pattern diagram. Also, this class implements the IGreetings interface because it is able to connect both incompatibles languages:
import { IGreetings } from "./greetings.interface";
import { Spanish } from "./spanish";
export class SpanishInterpreterAdapter implements IGreetings {
constructor(private spanish: Spanish) {}
sayHello(): void {
// the interpreter know's how to say hello in spanish
this.spanish.decirHola();
}
}
The Spanish class represents the "Adaptee" node of the Adapter Pattern diagram. We have a simple class with one method to say hello in spanish:
export class Spanish {
//sayHello means decirHola in Spanish
decirHola(): void {
console.log("Hola!");
}
}
This is our Profesional Tennis Player which represents the "Client" node of the Adapter Pattern diagram:
import { Spanish } from "./src/spanish";
import { SpanishInterpreterAdapter } from "./src/spanish-interpreter.adapter";
// our professional tenis now is playing an important match in Spain
// we need to hire an interpreter to translate their speech from English to Spanish
const spanishInterpreterAdapter = new SpanishInterpreterAdapter(new Spanish());
spanishInterpreterAdapter.sayHello();
// Hola! (means hello in english)
Often we can get "Facade pattern" and "Adapter pattern" confused. The main difference between they is their purpose: "facade pattern" simplifies interactions with a complex subsystem, while "adapter pattern" helps to make incompatible interfaces work together.
The adapter pattern is used when you need to adapt an existing class to meet the needs of a new interface, rather than simplifying access to a complex subsystem.
I hope that this article was useful for improve your design patterns skills.
See you in the next one!