源码: builder.py
# -.- coding:utf-8 -.-
"""
Builder模式, 解耦复杂条件组合的场景.
例如Subprocess运行外部程序文件, 要满足几种条件,
程序文件名、程序完整路径、程序工作目录、程序参数等等.
这种情况下, 如果要组合这些条件, 需要挨个判断, 所有逻辑都揉在一起.
使用builder模式, 可以不用写判断条件.
备注; 虽然不用写判断条件, 但要提供默认参数.
对于python而言, 要不要Builder模式其实并不重要!
因为python的函数可以再参数上提供默认值!
"""
# Director
class Subprocess(object):
@classmethod
def get_subdir(cls, dir):
return (LsCommand()
.add_argument("-l")
.add_argument(dir)
.spawn())
class LS(object):
def __init__(self):
self.command = "/bin/ls"
self.args = []
self.result = None
self.args.append(self.command)
# Builder
class LsCommand(object):
def __init__(self):
self.ls = LS()
def add_argument(self, argument):
self.ls.args.append(argument)
return self
def remove_argument(self, argument):
if argument in self.ls.args:
index = self.ls.args.index(argument)
self.ls.args.pop(index)
return self
def spawn(self):
import subprocess
stdout, stderr = (subprocess
.Popen(args=self.ls.args, stdout=subprocess.PIPE)
.communicate())
self.ls.result = stdout.decode("utf-8")
return self.ls
# Client
def main():
ls = Subprocess.get_subdir("/")
assert "lost+found" in ls.result
assert "/" in ls.args
assert "/bin/ls" in ls.args
assert "-l" in ls.args
if __name__ == '__main__':
main()
源码: builder2.py
# -.- coding:utf-8 -.-
"""
Builder模式, 解耦复杂条件组合的场景.
"""
from __future__ import print_function
class Car(object):
def __init__(self, wheels=4, seats=4, color="Black"):
self.wheels = wheels
self.seats = seats
self.color = color
def __str__(self):
msg = "This is a {0} car with {1} wheels and {2} seats."
return msg.format(self.color, self.wheels, self.seats)
class Builder:
def __init__(self):
self.car = Car()
def set_wheels(self, value):
raise NotImplementedError
def set_seats(self, value):
raise NotImplementedError
def set_color(self, value):
raise NotImplementedError
def get_result(self):
raise NotImplementedError
class CarBuilder(Builder):
def set_wheels(self, value):
self.car.wheels = value
return self
def set_seats(self, value):
self.car.seats = value
return self
def set_color(self, value):
self.car.color = value
return self
def get_result(self):
return self.car
# Director
class CarBuilderDirector(object):
@staticmethod
def construct():
return (
CarBuilder()
.set_wheels(8)
.set_seats(4)
.set_color("Red")
.get_result()
)
# Client
def main():
car = CarBuilderDirector.construct()
print(car)
if __name__ == '__main__':
main()
测试: tests/builder.py
# -.- coding:utf-8 -.-
import sys
import unittest
from design_patterns.creational import builder2
from design_patterns.creational import builder
class Builder(unittest.TestCase):
def test_car_builder(self):
car = builder2.CarBuilderDirector().construct()
self.assertEquals([car.color, car.seats, car.wheels],
["Red", 4, 8])
@unittest.skipIf(sys.platform == "win32", u"windows下无法运行linux命令")
def test_command_builder(self):
ls = builder.Subprocess.get_subdir("/")
self.assertTrue("lost+found" in ls.result)
self.assertTrue("/" in ls.args)
self.assertTrue("/bin/ls" in ls.args)
self.assertTrue("-l" in ls.args)
网友评论