Bridge pattern is used to decouple an abstraction from its implementation so that both can be changed independently.
Contents
- 1 Bridge Pattern’s Intent
- 2 Also Known As
- 3 Bridge Pattern’s Motivation
- 4 Bridge Pattern’s Applicability
- 5 Bridge Pattern’s Structure
- 6 Participants
- 7 Collaborations
- 8 Bridge Pattern’s Consequences
- 9 Bridge Pattern’s Implementation
- 10 Sample Code (Java Example)
- 11 Bridge Pattern’s Known Uses
- 12 Related Patterns
- 13 Non-Software Example
Bridge Pattern’s Intent
To decouple an abstraction from its implementation so that both can be changed independently.
Also Known As
Handle/Body
Bridge Pattern’s Motivation
Sometimes an abstraction should have different implementations; consider an object that handles persistence of objects over different platforms using either relational databases or file system structures (files and folders).
A simple implementation might choose to extend the object itself to implement the functionality for both file system and RDBMS. However this implementation would create a problem; Inheritance binds an implementation to the abstraction and thus it would be difficult to modify, extend, and reuse abstraction and implementation independently.
Bridge Pattern’s Applicability
Use bridge pattern when:
- To avoid permanent binding between abstraction and implementation.
- Both abstractions and implementations should be extensible by creating subclasses.
- Changes in implementation should have no impact on client.
- To share and implementation among multiple objects, and this fact should be hidden from client.
Bridge Pattern’s Structure
The structure of bridge pattern is as shown below:
Participants
Following are the participants in bridge pattern:
- Abstraction: Defines the abstraction interface and maintains a reference to an object of type Implementor.
- RefinedAbstraction: Extends the interface defined by Abstraction.
- Implementor: Defines the interface for implementation classes.
- ConcreteImplmentor: Implements the Implementor interface and defines its concrete implementation.
Collaborations
Abstraction forwards client requests to its Implementor object.
Bridge Pattern’s Consequences
The bridge pattern has the following consequences:
- Decoupling interface and implementation: An implementation is not bound permanently to an interface. The implementation of an abstraction can be configured at run-time. It’s even possible for an object to change its implementation at run-time.
- Improved extensibility: You can extend the Abstraction and Implementor hierarchies independently.
- Hiding implementation details from clients: You can shield clients from implementation details, like the sharing of implementor objects and the accompanying reference count mechanism.
Bridge Pattern’s Implementation
Following issues should be considered while implementing bridge pattern:
- Only one Implementor: In situations where there’s only one implementation, creating an abstract Implementor class isn’t necessary. This is a degenerate case of the Bridge pattern; there’s a one-to-one relationship between Abstraction and Implementor. Nevertheless, this separation is still useful when a change in the implementation of a class must not affect its existing clients—that is, they shouldn’t have to be recompiled, just relinked.
- Creating the right Implementor object: How, when, and where do you decide which Implementor class to instantiate when there’s more than one? If Abstraction knows about all ConcreteImplementor classes, then it can instantiate one of them in its constructor; it can decide between them based on parameters passed to its constructor. If, for example, a collection class supports multiple implementations, the decision can be based on the size of the collection. A linked list implementation can be used for small collections and a hash table for larger ones.
Sample Code (Java Example)
When we have interface hierarchies in both interfaces as well as implementations, then builder design pattern is used to decouple the interfaces from implementation and hiding the implementation details from the client programs.
The implementation of bridge design pattern follows the notion to prefer Composition over inheritance.
Let’s say we have an interface hierarchy in both interfaces and implementations like below image:
Now we will use bridge design pattern to decouple the interfaces from implementation and the UML diagram for the classes and interfaces after applying bridge pattern will look like below image:
Notice the bridge between Shape and Color interfaces and use of composition in implementing the bridge pattern.
Here is the java code for Shape and Color interfaces.
//Color.java
public interface Color {
public void applyColor();
}
//Shape.java
public abstract class Shape {
//Composition - implementor
protected Color color;
//constructor with implementor as input argument
public Shape(Color c){
this.color=c;
}
abstract public void applyColor();
}
We have Triangle and Pentagon implementation classes as below.
//Triangle.java
public class Triangle extends Shape{
public Triangle(Color c) {
super(c);
}
@Override
public void applyColor() {
System.out.print("Triangle filled with color ");
color.applyColor();
}
}
//Pentagon.java
public class Pentagon extends Shape{
public Pentagon(Color c) {
super(c);
}
@Override
public void applyColor() {
System.out.print("Pentagon filled with color ");
color.applyColor();
}
}
Here are the implementation classes for RedColor and GreenColor.
//RedColor.java
public class RedColor implements Color{
public void applyColor(){
System.out.println("red.");
}
}
//GreenColor.java
public class GreenColor implements Color{
public void applyColor(){
System.out.println("green.");
}
}
Lets test our bridge pattern implementation with a test program.
//BridgePatternTest.java
public class BridgePatternTest {
public static void main(String[] args) {
Shape tri = new Triangle(new RedColor());
tri.applyColor();
Shape pent = new Pentagon(new GreenColor());
pent.applyColor();
}
}
Bridge Pattern’s Known Uses
Following are the examples in Java API where bridge pattern is used:
new LinkedHashMap(LinkedHashSet<K>, List<V>) which returns an unmodifiable linked map which doesn’t clone the items, but uses them. The java.util.Collections#newSetFromMap() and singletonXXX()
Related Patterns
An Abstract Factory can create and configure a particular Bridge.
The Adapter pattern is geared toward making unrelated classes work together. It is usually applied to systems after they’re designed. Bridge, on the other hand, is used up-front in a design to let abstractions and implementations vary independently.
Non-Software Example
The Bridge pattern decouples an abstraction from its implementation, so that the two can vary independently. A household switch controlling lights, ceiling fans, etc. is an example of the Bridge. The purpose of the switch is to turn a device on or off. The actual switch can be implemented as a pull chain, a simple two position switch, or a variety of dimmer switches.
Suryateja Pericherla, at present is a Research Scholar (full-time Ph.D.) in the Dept. of Computer Science & Systems Engineering at Andhra University, Visakhapatnam. Previously worked as an Associate Professor in the Dept. of CSE at Vishnu Institute of Technology, India.
He has 11+ years of teaching experience and is an individual researcher whose research interests are Cloud Computing, Internet of Things, Computer Security, Network Security and Blockchain.
He is a member of professional societies like IEEE, ACM, CSI and ISCA. He published several research papers which are indexed by SCIE, WoS, Scopus, Springer and others.
Leave a Reply