首页 > 编程笔记

Python建造者模式(附带源码)

肯德基有薯条、鸡腿、鸡翅、鸡米花、可乐、橙汁、火腿汉堡、牛肉汉堡、鸡肉卷等单品,也有很多套餐。

比如,套餐1包括鸡翅、可乐、薯条;套餐2包括鸡腿、火腿汉堡、橙汁、薯条……

这种由各种各样的单品生成各种套餐的模式被称为建造者模式。

建造者模式将一个复杂对象的“构建”与它的“表示”进行分离,使得同样的构建过程可以创建不同的表示。

建造者模式与工厂方法模式是非常相似的。构建与表示分离和创建不同的表示对于工厂方法模式同样具备。建造者模式唯一区别于工厂方法模式的是针对复杂对象的构建。

也就是说:
当需要构建的产品具备复杂创建过程时,可以抽取出共性构建过程,然后交由具体实现类自定义构建流程,使得同样的构建行为可以生产出不同的产品,分离了构建与表示,使构建产品的灵活性大大增加。

Python建造者模式
图1:建造者模式

建造者模式(见图1)主要包含以下4种角色:
理解了建造者模式的4种角色,其实就已经掌握建造者模式的真谛:
这里列举一个现实世界的场景来理解建造者模式的实现。比如某快餐店的菜单上有三大类食品,分别是主食类、小食类和饮料类。每个大类别下又含有对应的单品,包含汉堡、鸡翅、薯条和可乐等。根据客人选择的单品可以一步一步来生成各种订单。

请看下面的 Python 代码:
class Burger():
    """
    主食类:名字和价格
    """
    name = ""
    price = 0.0
 
    def getPrice(self):
        return self.price
 
    def setPrice(self, price):
        self.price = price
 
    def getName(self):
        return self.name
 
 
class cheeseBurger(Burger):
    """
    奶酪汉堡
    """
 
    def _ _init_ _(self):
        self.name = "cheese burger"
        self.price = 10.0
 
 
class spicyChickenBurger(Burger):
    """
    香辣鸡汉堡
    """
 
    def _ _init_ _(self):
        self.name = "spicy chicken burger"
        self.price = 15.0
 
 
class Snack():
    """
    小吃类:名字、价格和类型
    """
    name = ""
    price = 0.0
    type = "SNACK"
 
    def getPrice(self):
        return self.price
 
    def setPrice(self, price):
        self.price = price
 
    def getName(self):
        return self.name
 
 
class chips(Snack):
    """
    薯条
    """
 
    def _ _init_ _(self):
        self.name = "chips"
        self.price = 6.0
 
 
class chickenWings(Snack):
    """
    鸡翅
    """
 
    def _ _init_ _(self):
        self.name = "chicken wings"
        self.price = 12.0
 
 
class Beverage():
    """
    饮料
    """
    name = ""
    price = 0.0
    type = "BEVERAGE"
 
    def getPrice(self):
        return self.price
 
    def setPrice(self, price):
        self.price = price
 
    def getName(self):
        return self.name
 
 
class coke(Beverage):
    """
    可乐
    """
 
    def _ _init_ _(self):
        self.name = "coke"
        self.price = 4.0
 
 
class milk(Beverage):
    """
    牛奶
    """
 
    def _ _init_ _(self):
        self.name = "milk"
        self.price = 5.0
 
 
class order():
    """
    订单对象,一个订单中包含一份主食、一份小吃、一瓶饮料
    """
    burger = ""
    snack = ""
    beverage = ""
 
    def _ _init_ _(self, orderBuilder):
        self.burger = orderBuilder.bBurger
        self.snack = orderBuilder.bSnack
        self.beverage = orderBuilder.bBeverage
 
    def show(self):
        print("Burger:%s" % self.burger.getName())
        print("Snack:%s" % self.snack.getName())
        print("Beverage:%s" % self.beverage.getName())
 
 
# 建造者
class orderBuilder():
    """
    orderBuilder就是建造者模式中所谓的“建造者”,
    将订单的构建与表示分离,以达到解耦的目的。
    在上面订单的构建过程中,如果将order直接通过参数定义好(其构建与表示没有分离),
    同时在多处进行订单生成,那么需要修改订单内容时
    则需要一处一处去修改,业务风险也就提高了不少
    """
    bBurger = ""
    bSnack = ""
    bBeverage = ""
 
    def addBurger(self, xBurger):
        self.bBurger = xBurger
 
    def addSnack(self, xSnack):
        self.bSnack = xSnack
 
    def addBeverage(self, xBeverage):
        self.bBeverage = xBeverage
 
    def build(self):
        return order(self)
 
 
# Director类
class orderDirector():
    """
    在建造者模式中,还可以添加一个Director类,用以安排已有模块的构造步骤。
   当建造者中有比较严格的顺序要求时,该类会有比较大的用处
    """
    order_builder = ""
 
    def _ _init_ _(self, order_builder):
        self.order_builder = order_builder
 
    def createOrder(self, burger, snack, beverage):
        self.order_builder.addBurger(burger)
        self.order_builder.addSnack(snack)
        self.order_builder.addBeverage(beverage)
        return self.order_builder.build()
 
 
# 场景实现
if _ _name_ _ == "_ _main_ _":
    order_builder = orderBuilder()
    order_builder.addBurger(spicyChickenBurger())
    order_builder.addSnack(chips())
    order_builder.addBeverage(milk())
    order_1 = order_builder.build()
    order_1.show()

建造者模式的适用场景

建造者模式的优点

在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建进行解耦,使得相同的创建过程可以创建不同的产品对象。

每一个具体建造者都是独立的,与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加具体建造者,用户使用不同的具体建造者可以得到不同的产品对象。由于导演者类针对抽象建造者编程,因此增加新的具体建造者时无须修改原有类库的代码,系统扩展方便,符合开闭原则。在编写代码时,代码重用率是尤为重要的。

用户可以更为精细地控制产品的创建过程,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便用户使用程序来控制创建过程。

建造者模式的缺点

建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异较大,例如很多组成部分不相同,则不适合使用建造者模式,因此其使用范围受到一定的限制。

如果产品的内部变化复杂,则可能需要很多具体建造者类实现这种变化,这会导致系统变得庞大,会增加系统的理解难度和运行成本。

推荐阅读