Skip to content

Bridge Design Pattern

Video Lecture

Section Video Links
Bridge Overview Bridge Overview Bridge Overview Bridge Overview 
Bridge Use Case Bridge Use Case Bridge Use Case Bridge Use Case 
Python Tuple Python Tuple Python Tuple Python Tuple 
Python *args Python *args Python *args Python *args 

Overview

...Refer to Book or Videos for extra content.

Terminology

...Refer to Book or Videos for extra content.

Bridge UML Diagram

Bridge Pattern UML Diagram

Source Code

...Refer to Book or Videos for extra content.

./bridge/bridge_concept.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# pylint: disable=too-few-public-methods
"Bridge Pattern Concept Sample Code"
from abc import ABCMeta, abstractmethod

class IAbstraction(metaclass=ABCMeta):
    "The Abstraction Interface"

    @staticmethod
    @abstractmethod
    def method(*args):
        "The method handle"

class RefinedAbstractionA(IAbstraction):
    "A Refined Abstraction"

    def __init__(self, implementer):
        self.implementer = implementer()

    def method(self, *args):
        self.implementer.method(*args)

class RefinedAbstractionB(IAbstraction):
    "A Refined Abstraction"

    def __init__(self, implementer):
        self.implementer = implementer()

    def method(self, *args):
        self.implementer.method(*args)

class IImplementer(metaclass=ABCMeta):
    "The Implementer Interface"

    @staticmethod
    @abstractmethod
    def method(*args: tuple) -> None:
        "The method implementation"

class ConcreteImplementerA(IImplementer):
    "A Concrete Implementer"

    @staticmethod
    def method(*args: tuple) -> None:
        print(args)

class ConcreteImplementerB(IImplementer):
    "A Concrete Implementer"

    @staticmethod
    def method(*args: tuple) -> None:
        for arg in args:
            print(arg)

# The Client
REFINED_ABSTRACTION_A = RefinedAbstractionA(ConcreteImplementerA)
REFINED_ABSTRACTION_A.method('a', 'b', 'c')

REFINED_ABSTRACTION_B = RefinedAbstractionB(ConcreteImplementerB)
REFINED_ABSTRACTION_B.method('a', 'b', 'c')

Output

1
2
3
4
5
python ./bridge/bridge_concept.py
('a', 'b', 'c')
a
b
c

Example Use Case

...Refer to Book or Videos for extra content.

Example UML Diagram

Bridge Pattern in Context

Source Code

./bridge/client.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
"Bridge Pattern Concept Sample Code"

from circle_implementer import CircleImplementer
from square_implementer import SquareImplementer
from circle import Circle
from square import Square

CIRCLE = Circle(CircleImplementer)
CIRCLE.draw()

SQUARE = Square(SquareImplementer)
SQUARE.draw()

./bridge/circle_implementer.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# pylint: disable=too-few-public-methods
"A Circle Implementer"
from interface_shape_implementer import IShapeImplementer

class CircleImplementer(IShapeImplementer):
    "A Circle Implementer"

    def draw_implementation(self):
        print("    ******")
        print("  **      **")
        print(" *          *")
        print("*            *")
        print("*            *")
        print(" *          *")
        print("  **      **")
        print("    ******")

./bridge/square_implementer.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# pylint: disable=too-few-public-methods
"A Square Implementer"
from interface_shape_implementer import IShapeImplementer

class SquareImplementer(IShapeImplementer):
    "A Square Implementer"

    def draw_implementation(self):
        print("**************")
        print("*            *")
        print("*            *")
        print("*            *")
        print("*            *")
        print("*            *")
        print("*            *")
        print("**************")

./bridge/circle.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# pylint: disable=too-few-public-methods
"A Circle Abstraction"
from interface_shape import IShape

class Circle(IShape):
    "The Circle is a Refined Abstraction"

    def __init__(self, implementer):
        self.implementer = implementer()

    def draw(self):
        self.implementer.draw_implementation()

./bridge/square.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# pylint: disable=too-few-public-methods
"A Square Abstraction"
from interface_shape import IShape

class Square(IShape):
    "The Square is a Refined Abstraction"

    def __init__(self, implementer):
        self.implementer = implementer()

    def draw(self):
        self.implementer.draw_implementation()

./bridge/interface_shape_implementer.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# pylint: disable=too-few-public-methods
"A Shape Implementor Interface"
from abc import ABCMeta, abstractmethod

class IShapeImplementer(metaclass=ABCMeta):
    "Shape Implementer"

    @staticmethod
    @abstractmethod
    def draw_implementation():
        "The method that the refined abstractions will implement"

./bridge/interface_shape.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# pylint: disable=too-few-public-methods
"The Shape Abstraction Interface"
from abc import ABCMeta, abstractmethod

class IShape(metaclass=ABCMeta):
    "The Shape Abstraction Interface"

    @staticmethod
    @abstractmethod
    def draw():
        "The method that will be handled at the shapes implementer"

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
python ./bridge/client.py
    ******
  **      **
 *          *
*            *
*            *
 *          *
  **      **
    ******
**************
*            *
*            *
*            *
*            *
*            *
*            *
**************

New Coding Concepts

Python Tuple

A Python Tuple is similar to a List. Except that the items in the Tuple are ordered, unchangeable and allow duplicates.

A Tuple can be instantiated using the round brackets () or tuple() , verses [] for a List and {} for a Set or Dictionary.

1
2
3
4
5
6
PS> python
>>> items = ("alpha", "bravo", "charlie", "alpha")
>>> print(items)
('alpha', 'bravo', 'charlie', 'alpha')
>>> print(len(items))
4

The *args Argument.

The *args argument takes all arguments that were sent to this method, and packs them into a Tuple.

It is useful when you don't know how many arguments, or what types, will be sent to a method, and you want your method to be able support any number of arguments and types being sent to it.

If you want your method to be strict about the types that it can accept, the set it specifically to accept List, Dictionary, Set or Tuple, and treat the argument as such within the method body, but the *args argument is another common option that you will see throughout source code examples on the internet.

E.g., when using the *args in your method signature, you can call it with any number of arguments of any type.

1
2
3
4
5
6
7
8
def my_method(*args):

    print(type(args))

    for arg in args:
        print(arg)

my_method(1, 22, [3], {4})

Outputs

1
2
3
4
5
<class 'tuple'>
1
22
[3]
{4}

Summary

...Refer to Book or Videos for extra content.