As a material for learning GoF design patterns, the book "Introduction to Design Patterns Learned in the Augmented and Revised Java Language" seems to be helpful. However, since the examples taken up are based on JAVA, I tried the same practice in Python to deepen my understanding.
The Bridge pattern is one of the design patterns defined by GoF (Gang of Four; 4 gangs). The purpose is to extend the class in multiple directions by preparing a "bridging" class.
UML class and sequence diagram UML class diagram (The above is quoted from Wikipedia)
The Bridge pattern seems to bridge the ** feature class hierarchy ** and the ** implementation class hierarchy **.
If you want to add new functionality to a class, define a new subclass and implement the method. The relationship between an existing superclass and a newly defined subclass is the "functional class hierarchy". In general, assume the following relationships.
--Superclass has basic functions --Add new features in subclasses
If you want to add a new implementation, define a concrete subclass derived from the abstract class and then implement the method. The relationship between an existing abstract class and a newly derived concrete subclass is the "implementation class hierarchy". In general, assume the following relationships.
--In the abstract class, the interface is defined by the abstract method. --Derived subclasses implement their interface with concrete methods
I would like to actually run a sample program that utilizes the Bridge pattern and check the following behavior. This is a sample that assumes a bridge between the ** function class hierarchy ** and the ** implementation class hierarchy **.
--Display a string through the bridge between DisplayFunc
and DisplayStringImpl
--Display a string through the bridge between DisplayCountFunc
and DisplayStringImpl
--Display a string through the bridge between DisplayCountFunc
and DisplayStringImpl
--The character string is displayed repeatedly 5 times through the bridge between DisplayRandomFunc
and DisplayStringImpl
.
--The character string is displayed repeatedly at random times through the bridge between DisplayRandomFunc
and DisplayStringImpl
.
--Display the contents of the text file via the bridge between DisplayFunc
and DisplayTextfileImpl
$ python Main.py
+-----------+
|Hello Japan|
+-----------+
+-----------+
|Hello Japan|
+-----------+
+--------------+
|Hello Universe|
+--------------+
+--------------+
|Hello Universe|
|Hello Universe|
|Hello Universe|
|Hello Universe|
|Hello Universe|
+--------------+
+--------------+
|Hello Universe|
|Hello Universe|
|Hello Universe|
|Hello Universe|
+--------------+
aaa
bbb
ccc
ddd
eee
fff
ggg
If you just run the sample program, you don't really know what you want to do. Next, let's check the details of the sample program.
Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Bridge
--Directory structure
.
├── Main.py
├── bridge
│ ├── __init__.py
│ ├── function
│ │ ├── __init__.py
│ │ ├── display_count_func.py
│ │ ├── display_func.py
│ │ └── display_random_func.py
│ └── implement
│ ├── __init__.py
│ ├── display_impl.py
│ ├── display_string_impl.py
│ └── display_textfile_impl.py
└── test.txt
It is a class that implements only basic functions using the method of ʻImplement. In the sample program, the
DisplayFunc` class serves this role.
bridge/function/display_func.py
class DisplayFunc(object):
def __init__(self, impl):
self.impl = impl
def open(self):
self.impl.rawOpen()
def print_body(self):
self.impl.rawPrint()
def close(self):
self.impl.rawClose()
def display(self):
self.open()
self.print_body()
self.close()
ʻAbstractionThis is a role with additional functions. In the sample program, the
DisplayCountFunc class and the
DisplayRandomFunc` class serve this role.
bridge/function/display_count_func.py
from bridge.function.display_func import DisplayFunc
class DisplayCountFunc(DisplayFunc):
def __init__(self, impl):
super(DisplayCountFunc, self).__init__(impl)
def multiDisplay(self, times):
self.open()
for _ in range(times):
self.print_body()
self.close()
bridge/function/display_random_func.py
import random
from bridge.function.display_func import DisplayFunc
class DisplayRandomFunc(DisplayFunc):
def __init__(self, impl):
super(DisplayRandomFunc, self).__init__(impl)
def randomDisplay(self, times):
self.open()
t = random.randint(0, times)
for _ in range(t):
self.print_body()
self.close()
ʻAbstractionThis is the role that defines the method for implementing the interface. In the sample program, the
DisplayImpl` class serves this role.
bridge/implement/display_impl.py
from abc import ABCMeta, abstractmethod
class DisplayImpl(metaclass=ABCMeta):
@abstractmethod
def rawOpen(self):
pass
@abstractmethod
def rawPrint(self):
pass
@abstractmethod
def rawClose(self):
pass
Specifically, it is the role of implementing the interface of the role of ʻImplement. In the sample program, the
DisplayStringImpl class and the
DisplayTextfileImpl` class serve this role.
bridge/implement/display_string_impl.py
from bridge.implement.display_impl import DisplayImpl
class DisplayStringImpl(DisplayImpl):
def __init__(self, string):
self.string = string
self.width = len(string)
def rawOpen(self):
self.printLine()
def rawPrint(self):
print("|{0}|".format(self.string))
def rawClose(self):
self.printLine()
print("")
def printLine(self):
line = '-' * self.width
print("+{0}+".format(line))
bridge/implement/display_textfile_impl.py
from bridge.implement.display_impl import DisplayImpl
class DisplayTextfileImpl(DisplayImpl):
def __init__(self, filename):
self.filename = filename
def rawOpen(self):
filename = self.filename
self.f = open(filename, "r")
def rawPrint(self):
data = self.f.read()
data = data.split('\n')
for l in data:
print(l)
def rawClose(self):
self.f.close()
In the sample program, the startMain
method serves this role.
Main.py
from bridge.function.display_func import DisplayFunc
from bridge.function.display_count_func import DisplayCountFunc
from bridge.function.display_random_func import DisplayRandomFunc
from bridge.implement.display_string_impl import DisplayStringImpl
from bridge.implement.display_textfile_impl import DisplayTextfileImpl
def startMain():
d1 = DisplayFunc(DisplayStringImpl("Hello Japan"))
d2 = DisplayCountFunc(DisplayStringImpl("Hello Japan"))
d3 = DisplayCountFunc(DisplayStringImpl("Hello Universe"))
d4 = DisplayRandomFunc(DisplayStringImpl("Hello Universe"))
d5 = DisplayFunc(DisplayTextfileImpl("test.txt"))
d1.display()
d2.display()
d3.display()
d3.multiDisplay(5)
d4.randomDisplay(5)
d5.display()
if __name__ == '__main__':
startMain()
-[Finishing "Introduction to Design Patterns Learned in Java Language" (Not)](https://medium.com/since-i-want-to-start-blog-that-looks-like-men-do/java Introduction to Design Patterns Learned in Language-Finishing-Not-2cc9b34a30b2) -Bridge pattern from "diary of tachikawa844"
Recommended Posts