Skip to main content

Real World Implementation Of Brideg Pattern

Real World Implementation

Let's consider a server-side application where we need to work with different types of databases (such as PostgreSQL, MongoDB, etc.). These databases have different methods for connecting, executing queries, etc. The Bridge pattern can be used here to create a uniform interface for the client to interact with the databases while hiding the complexity and specifics of each database type.

Here's an example in TypeScript:

1. Implementor interface and concrete implementors:

interface Database {
connect(): void;

query(sql: string): any;

close(): void;
}

class PostgreSQLDatabase implements Database {
connect(): void {
console.log("Connecting to PostgreSQL database.");
}

query(sql: string): any {
console.log(`Executing query '${sql}' on PostgreSQL database.`);
// Implementation of query execution
}

close(): void {
console.log("Closing connection to PostgreSQL database.");
}
}

class MongoDBDatabase implements Database {
connect(): void {
console.log("Connecting to MongoDB database.");
}

query(sql: string): any {
console.log(`Executing query '${sql}' on MongoDB database.`);
// Implementation of query execution
}

close(): void {
console.log("Closing connection to MongoDB database.");
}
}

2. Abstraction and refined abstractions:

abstract class DatabaseService {
protected database: Database;

constructor(database: Database) {
this.database = database;
}

abstract fetchData(query: string): any;
}

class ClientDatabaseService extends DatabaseService {
fetchData(query: string): any {
this.database.connect();
const result = this.database.query(query);
this.database.close();
return result;
}
}

3. Client code:

let databaseService = new ClientDatabaseService(new PostgreSQLDatabase());
databaseService.fetchData("SELECT * FROM users;"); // use PostgreSQL database

databaseService = new ClientDatabaseService(new MongoDBDatabase());
databaseService.fetchData("db.users.find({})"); // use MongoDB database

In this example, we've created a "bridge" that decouples the high-level DatabaseService class from the specifics of the various Database implementations. By doing this, you can add a new type of database to the application without changing the DatabaseService class or the client code. Also, at runtime, the client can decide which database to use.

Advantages Of Using The Bridge Pattern

Here are some advantages offered by the Bridge pattern:

Decoupling of Abstraction and Implementation

The Bridge pattern allows the abstraction (DatabaseService) and the implementation (Database) to vary independently. This means that you can change the implementation without affecting the abstraction, and vice versa.

For instance, if you want to add a new type of database (e.g., MySQL), you only need to add a new class implementing the Database interface. This won't affect the DatabaseService class or the client code.

class MySQLDatabase implements Database {
connect(): void {
console.log("Connecting to MySQL database.");
}

query(sql: string): any {
console.log(`Executing query '${sql}' on MySQL database.`);
// Implementation of query execution
}

close(): void {
console.log("Closing connection to MySQL database.");
}
}

let databaseService = new ClientDatabaseService(new MySQLDatabase());
databaseService.fetchData("SELECT * FROM users;"); // use MySQL database

Improved Readability and Maintainability

By separating the high-level logic from the low-level details, the Bridge pattern improves code readability and maintainability.

Looking at the DatabaseService class, it's easy to understand its purpose without getting bogged down in the specifics of how each type of database operates. Those specifics are encapsulated within the Database implementations.

abstract class DatabaseService {
protected database: Database;

constructor(database: Database) {
this.database = database;
}

abstract fetchData(query: string): any;
}

Runtime Binding

The Bridge pattern enables changing the implementation at runtime. In the client code, you can easily switch from using a PostgreSQLDatabase to a MongoDBDatabase just by instantiating a new ClientDatabaseService with a different Database object.

let databaseService = new ClientDatabaseService(new PostgreSQLDatabase());
databaseService.fetchData("SELECT * FROM users;"); // use PostgreSQL database

databaseService = new ClientDatabaseService(new MongoDBDatabase());
databaseService.fetchData("db.users.find({})"); // use MongoDB database
TypeScript Course Instructor Image
TypeScript Course Instructor Image

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 DETAILS

What 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.

YouTube @cloudaffle