What is the Bridge Design Pattern?
The Bridge design pattern is a structural design pattern that separates the abstraction of an object from its implementation so that they can be developed independently.
It does this by creating a bridge between the abstraction and the implementation, allowing them to vary independently of each other.
The Bridge pattern consists of two main components:
Abstraction: This defines the high-level interface of an object, and delegates the implementation details to an Implementor object.
Implementor: This defines the interface for concrete implementations, which are then used by the Abstraction object.
By separating the Abstraction from the Implementor, the Bridge pattern provides greater flexibility and extensibility to the system. It also allows the Abstraction and the Implementor to vary independently, which can lead to more reusable code.
Overall, the Bridge pattern is useful in situations where there are multiple implementations of an abstraction, and where changes to the implementation should not affect the Abstraction interface.
This pattern is commonly used in GUI toolkits, where the abstraction is the widget, and the implementor is the toolkit-specific code that renders the widget.
Implementation
Here's an example of how the Bridge design pattern can be implemented in JavaScript:
// Implementation interface
class Implementor {
operation() {}
}
// Concrete implementation classes
class ConcreteImplementorA extends Implementor {
operation() {
return "ConcreteImplementorA";
}
}
class ConcreteImplementorB extends Implementor {
operation() {
return "ConcreteImplementorB";
}
}
// Abstraction interface
class Abstraction {
constructor(implementor) {
this.implementor = implementor;
}
operation() {}
}
// Refined abstraction classes
class RefinedAbstraction extends Abstraction {
operation() {
return `RefinedAbstraction with ${this.implementor.operation()}`;
}
}
// Usage
const implementorA = new ConcreteImplementorA();
const implementorB = new ConcreteImplementorB();
const abstraction1 = new RefinedAbstraction(implementorA);
const abstraction2 = new RefinedAbstraction(implementorB);
console.log(abstraction1.operation()); // Output: RefinedAbstraction with ConcreteImplementorA
console.log(abstraction2.operation()); // Output: RefinedAbstraction with ConcreteImplementorB
In this example, the Implementor
interface defines the operations that concrete implementors must implement. The ConcreteImplementorA
and ConcreteImplementorB
classes are two examples of concrete implementors that implement the operation
method in their own way.
The Abstraction
interface defines the methods that abstractions must implement. In this case, we only have one method, operation
, which is delegated to the implementor
object. The RefinedAbstraction
class is a concrete implementation of Abstraction
that uses a specific Implementor
object to perform its operation.
Finally, we create two instances of RefinedAbstraction
, each with a different Implementor
object. We call the operation
method on each instance to see the output, which demonstrates how the Bridge pattern allows us to separate the abstraction from its implementation.
Thank you for taking the time to read this article! 😄
Top comments (0)