Bridge pattern


The bridge pattern is a design pattern used in software engineering that is meant to "decouple an abstraction from its implementation so that the two can vary independently", introduced by the Gang of Four. The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.
When a class varies often, the features of object-oriented programming become very useful because changes to a program's code can be made easily with minimal prior knowledge about the program. The bridge pattern is useful when both the class and what it does vary often. The class itself can be thought of as the abstraction and what the class can do as the implementation. The bridge pattern can also be thought of as two layers of abstraction.
When there is only one fixed implementation, this pattern is known as the Pimpl idiom in the C++ world.
The bridge pattern is often confused with the adapter pattern, and is often implemented using the object adapter pattern, e.g. in the Java code below.
Variant: The implementation can be decoupled even more by deferring the presence of the implementation to the point where the abstraction is utilized.

Overview

The Bridge
design pattern is one of the twenty-three well-known
GoF design patterns
that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.
What problems can the Bridge design pattern solve?
When using subclassing, different subclasses implement an abstract class in different ways. But an implementation is bound to the abstraction at compile-time and cannot be changed at run-time.
What solution does the Bridge design pattern describe?
This enables to configure an Abstraction with an Implementor object at run-time.
See also the Unified Modeling Language class and sequence diagram below.

Structure

UML class and sequence diagram

In the above Unified Modeling Language class diagram, an abstraction is not implemented as usual in a single inheritance hierarchy.
Instead, there is one hierarchy for
an abstraction and a separate hierarchy for its implementation, which makes the two independent from each other.
The Abstraction interface is implemented in terms of
the Implementor interface.
The UML sequence diagram
shows the run-time interactions: The Abstraction1 object delegates implementation to the Implementor1 object,
which performs the operation and returns to Abstraction1.

Class diagram

; Abstraction
; RefinedAbstraction
; Implementor
; ConcreteImplementor

Example

C#

Bridge pattern compose objects in tree structure. It decouples abstraction from implementation. Here abstraction represents the client from which the objects will be called. An example implemented in C# is given below

// Helps in providing truly decoupled architecture
public interface IBridge
public class Bridge1 : IBridge
public class Bridge2 : IBridge
public interface IAbstractBridge
public class AbstractBridge : IAbstractBridge

The Bridge classes are the Implementation that uses the same interface-oriented architecture to create objects. On the other hand, the abstraction takes an instance of the implementation class and runs its method. Thus, they are completely decoupled from one another.

Crystal


abstract class DrawingAPI
abstract def draw_circle
end
class DrawingAPI1 < DrawingAPI
def draw_circle
"API1.circle at #:# - radius: #"
end
end
class DrawingAPI2 < DrawingAPI
def draw_circle
"API2.circle at #:# - radius: #"
end
end
abstract class Shape
protected getter drawing_api : DrawingAPI
def initialize
end
abstract def draw
abstract def resize_by_percentage
end
class CircleShape < Shape
getter x : Float64
getter y : Float64
getter radius : Float64
def initialize
super
end
def draw
@drawing_api.draw_circle
end
def resize_by_percentage
@radius *=
end
end
class BridgePattern
def self.test
shapes = of Shape
shapes << CircleShape.new
shapes << CircleShape.new
shapes.each do |shape|
shape.resize_by_percentage
puts shape.draw
end
end
end
BridgePattern.test

Output

API1.circle at 1.0:2.0 - radius: 3.075
API2.circle at 5.0:7.0 - radius: 11.275

C++


  1. include
  2. include
  3. include
class DrawingAPI ;
class DrawingAPI01 : public DrawingAPI ;
class DrawingAPI02 : public DrawingAPI ;
class Shape ;
class CircleShape: public Shape ;
int main

Output:

API01.circle at 1.000000:2.000000 - radius: 3.075000
API02.circle at 5.000000:7.000000 - radius: 11.275000

Java

The following Java program defines a bank account that separates the account operations from the logging of these operations.

// Logger has two implementations: info and warning
@FunctionalInterface
interface Logger
abstract class AbstractAccount
class SimpleAccount extends AbstractAccount
public class BridgeDemo

It will output:

info: withdraw 75 result true
warning: withdraw 10 result true
warning: withdraw 100 result false

PHP


interface DrawingAPI
class DrawingAPI1 implements DrawingAPI
class DrawingAPI2 implements DrawingAPI
abstract class Shape
class CircleShape extends Shape
class Tester
Tester::main;

Output:
API1.circle at 1:3 radius 17.5
API2.circle at 5:7 radius 27.5

Scala


trait DrawingAPI
class DrawingAPI1 extends DrawingAPI
class DrawingAPI2 extends DrawingAPI
abstract class Shape
class CircleShape
extends Shape
object BridgePattern

Python


"""
Bridge pattern example.
"""
from abc import ABCMeta, abstractmethod
NOT_IMPLEMENTED = "You should implement this."
class DrawingAPI:
__metaclass__ = ABCMeta
@abstractmethod
def draw_circle:
raise NotImplementedError
class DrawingAPI1:
def draw_circle:
return "API1.circle at : - radius: ".format
class DrawingAPI2:
def draw_circle:
return "API2.circle at : - radius: ".format
class DrawingAPI3:
def draw_circle:
return "API3.circle at : - radius: ".format
class Shape:
__metaclass__ = ABCMeta
drawing_api = None
def __init__:
self.drawing_api = drawing_api
@abstractmethod
def draw:
raise NotImplementedError
@abstractmethod
def resize_by_percentage:
raise NotImplementedError
class CircleShape:
def __init__:
self.x = x
self.y = y
self.radius = radius
super.__init__
def draw:
return self.drawing_api.draw_circle
def resize_by_percentage:
self.radius *=
class BridgePattern:
@staticmethod
def test:
shapes =
for shape in shapes:
shape.resize_by_percentage
print)
BridgePattern.test