Real World Implementation Of Adapter Pattern
Consider the following scenario: your application uses a MySQL database, but you need to switch to a PostgreSQL database. The two databases use different methods for establishing connections, executing queries, and so on.
Here's a class diagram for the database example using the Adapter pattern,
This diagram illustrates the relationship between
the MySQLDatabase, PostgreSQLDatabase, and DatabaseAdapter classes.
The DatabaseAdapter adapts the PostgreSQLDatabase to the MySQLDatabase
interface, allowing instances of PostgreSQLDatabase to be used
where MySQLDatabase instances were expected.
Real World Implementation
First, let's define the original MySQL class:
class MySQLDatabase {
connectToMySQL(uri: string): void {
console.log(`Connecting to MySQL database at ${uri}`);
// Implementation...
}
executeMySQLQuery(query: string): void {
console.log(`Executing MySQL query: ${query}`);
// Implementation...
}
}
Your application code may be scattered with calls to these methods, like this:
let database = new MySQLDatabase();
database.connectToMySQL("mysql://localhost:3306/mydb");
database.executeMySQLQuery("SELECT * FROM users");
Now, you decide to switch to PostgreSQL, but you can't just replace
the MySQLDatabase instances with PostgreSQLDatabase instances, because
the PostgreSQLDatabase class has a different interface:
class PostgreSQLDatabase {
connectToPostgres(uri: string): void {
console.log(`Connecting to PostgreSQL database at ${uri}`);
// Implementation...
}
executePostgresQuery(query: string): void {
console.log(`Executing PostgreSQL query: ${query}`);
// Implementation...
}
}
Here's where the Adapter pattern comes in. You can create an adapter class that
translates the MySQLDatabase interface to the PostgreSQLDatabase interface:
class DatabaseAdapter {
private database = new PostgreSQLDatabase();
connectToMySQL(uri: string): void {
this.database.connectToPostgres(uri);
}
executeMySQLQuery(query: string): void {
this.database.executePostgresQuery(query);
}
}
Now, you can use DatabaseAdapter in your application where MySQLDatabase was
expected:
let database = new DatabaseAdapter();
database.connectToMySQL("mysql://localhost:3306/mydb");
database.executeMySQLQuery("SELECT * FROM users");
The DatabaseAdapter makes your application believe it's still working with
a MySQLDatabase, but under the hood, it uses a PostgreSQLDatabase. This
allows you to switch databases with minimal changes to your application's code.
Advantages Of The Adapter Pattern
The Adapter pattern offers several advantages.
Reusability and flexibility
The Adapter pattern allows developers to reuse existing code without significant modifications. This is particularly useful when dealing with legacy code or third-party libraries.
In the above example, the PostgreSQLDatabase class can be reused without
any changes, even though its interface doesn't match the interface used by
the rest of the application:
class PostgreSQLDatabase {
connectToPostgres(uri: string): void {
console.log(`Connecting to PostgreSQL database at ${uri}`);
// Implementation...
}
executePostgresQuery(query: string): void {
console.log(`Executing PostgreSQL query: ${query}`);
// Implementation...
}
}
Decoupling
The Adapter pattern helps in decoupling the client and the services which reduces the dependencies between them. Changes to one component do not directly impact others. This makes the code more maintainable.
In the given example, if the PostgreSQLDatabase class changes, the rest of
the application isn't affected, because these changes are encapsulated in
the DatabaseAdapter class:
class DatabaseAdapter {
private database = new PostgreSQLDatabase();
connectToMySQL(uri: string): void {
this.database.connectToPostgres(uri);
}
executeMySQLQuery(query: string): void {
this.database.executePostgresQuery(query);
}
}
Enabling interoperability
The Adapter pattern can help different parts of a system work together even if their interfaces don't match. This is especially important when you want to integrate existing components or libraries into your application.
In our example, the DatabaseAdapter class enables the PostgreSQLDatabase
to work with the rest of the application that expects a MySQLDatabase
interface:
let database = new DatabaseAdapter();
database.connectToMySQL("mysql://localhost:3306/mydb");
database.executeMySQLQuery("SELECT * FROM users");
The Adapter pattern is best used when it solves a specific problem like integrating an incompatible interface or when it simplifies the codebase by hiding complex or unnecessary details.


Time To Transition From JavaScript To TypeScript
Level Up Your TypeScript And Object Oriented Programming Skills. The only complete TypeScript course on the marketplace you building TypeScript apps like a PRO.
SEE COURSE DETAILSWhat Can You Do Next 🙏😊
If you liked the article, consider subscribing to Cloudaffle, my YouTube Channel, where I keep posting in-depth tutorials and all edutainment stuff for ssoftware developers.