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