Bridge Design Pattern
Structural: Bridge Pattern
What is the Bridge Design Pattern in Modern JavaScript?
View Answer:
Here's an example using modern JavaScript (ES6).
// The abstraction
class SmartDevice {
constructor(operatingSystem) {
this.operatingSystem = operatingSystem;
}
turnOn() {
this.operatingSystem.start();
}
turnOff() {
this.operatingSystem.shutDown();
}
}
// The implementation
class OperatingSystem {
start() {
throw new Error("This method must be overwritten!");
}
shutDown() {
throw new Error("This method must be overwritten!");
}
}
class Android extends OperatingSystem {
start() {
console.log("Starting the Android system...");
}
shutDown() {
console.log("Shutting down the Android system...");
}
}
class iOS extends OperatingSystem {
start() {
console.log("Starting the iOS system...");
}
shutDown() {
console.log("Shutting down the iOS system...");
}
}
// Using the Bridge Design Pattern
const myAndroidDevice = new SmartDevice(new Android());
myAndroidDevice.turnOn(); // Output: Starting the Android system...
const myIOSDevice = new SmartDevice(new iOS());
myIOSDevice.turnOn(); // Output: Starting the iOS system...
In this example, SmartDevice
is our abstraction that we want to decouple from its implementation (the OperatingSystem
), allowing each to vary independently. The SmartDevice
class isn't concerned with how the OperatingSystem
is implemented, and similarly, the OperatingSystem
doesn't care how it's used by SmartDevice
. This makes it easy to add new types of devices and operating systems without modifying existing code.
The Bridge pattern belongs to which design pattern family?
View Answer:
What is the use case for the Bridge Pattern in JavaScript?
View Answer:
What are the objects that participate in the Bridge Pattern?
View Answer:
Objects that participate in the Bridge pattern include:
1. Abstraction: defines the abstraction's interface and maintains a reference to an object of type Implementor
.
2. RefinedAbstraction: extends the interface defined by Abstraction
.
3. Implementor: defines the interface for implementation classes. This interface doesn't have to correspond exactly to Abstraction
's interface; in fact, the two interfaces can be quite different.
4. ConcreteImplementor: implements the Implementor
interface and defines its concrete implementation.
Here's a code example in modern JavaScript (ES6) which showcases these components.
// Implementor
class DrawingAPI {
drawCircle(x, y, radius) {
throw new Error('This method must be overridden!');
}
}
// ConcreteImplementor 1
class DrawingAPI1 extends DrawingAPI {
drawCircle(x, y, radius) {
console.log(`API1.circle at ${x}:${y} radius ${radius}`);
}
}
// ConcreteImplementor 2
class DrawingAPI2 extends DrawingAPI {
drawCircle(x, y, radius) {
console.log(`API2.circle at ${x}:${y} radius ${radius}`);
}
}
// Abstraction
class Shape {
constructor(drawingAPI) {
if (this.constructor === Shape) {
throw new Error('Cannot instantiate abstract class!');
}
this.drawingAPI = drawingAPI;
}
draw() {
throw new Error('This method must be overridden!');
}
resizeByPercentage(pct) {
throw new Error('This method must be overridden!');
}
}
// RefinedAbstraction
class CircleShape extends Shape {
constructor(x, y, radius, drawingAPI) {
super(drawingAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
draw() {
this.drawingAPI.drawCircle(this.x, this.y, this.radius);
}
resizeByPercentage(pct) {
this.radius *= pct;
}
}
// Usage:
const shapes = [
new CircleShape(1, 2, 3, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2())
];
for (let shape of shapes) {
shape.resizeByPercentage(2.5);
shape.draw();
}
What are some of the advantages of employing the Bridge pattern?
View Answer:
- Loosely coupled code - Because the bridge pattern decouples an abstraction from its implementation, changes to the implementation do not affect the client code. The client code does not need to be compiled when the implementation changes.
- Reduces code duplication while increasing code maintainability and reusability.
- Classes and applications that are platform agnostic can be created.
- Helps to promote the Open-Closed principle, new abstractions and implementations can be developed independently.
- Decoupling abstraction from implementation: bridge pattern can avoid the binding between abstraction and implementation and select the implementation at run time.
- Improved Extensibility – Abstraction and implementation can be extended independently.
What are some of the disadvantages of employing the Bridge pattern?
View Answer:
- Bridge pattern implementation increases code complexity.
- Interfaces with only a single implementation.
- Using the technique in a highly cohesive class may cause the code to become more complicated.