引入建造者模式
肯德基的菜单上有薯条,鸡腿,鸡翅,鸡米花,可乐,橙汁等这些单品,也有很多套餐。
比如
套餐1:鸡翅,至尊虾汉堡,可乐,薯条
套餐2:鸡腿,火腿汉堡,橙汁,薯条
套餐3: 。。。。。
全家桶:。。。。。
这种有各种各样的单品一步一步生成各种套餐, 这种过程称的上建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象,有点像造房子一样一步步从地基做起到万丈高楼。我想这也是为什么被称呼为建造者模式的原因吧!
建造者的定义
将一个复杂对象的构建与他的表示进行分离,使得同样的构建过程可以创建不同的表示。
这个定义里面的 '不同表示' 意思是不同的产品,或者是不同的功能。
简单理解:建造者模式(Builder Pattern)具备两层含义:
- 构建于表示分离:构建代表对象创建,表示对象行为/方法,也就是对象的创建于行为进行分离(对应java代码,其实就是使用接口规定行为,然后由具体的实现类进行构建)
- 创建不同的表示:也就是具备同样的行为,但是却由于构建的行为顺序不同或其他原因可以创建出不同的表示。
我们看完上述建造者模式的定义,就知道它与工厂模式是非常相似的。构建于表示分离
和创建不同的表示
对于工厂模式同样具备。建造者模式唯一区别于工厂模式主要是针对复杂对象的构建
。也就是说,如果是创建简单对象,我们通常都是使用工厂模式进行创建;如果是创建复杂对象,那么就要考虑使用建造者模式。
主要解决
当需要构建的产品具备复杂创建
过程时,可以抽取出共性构建过程,然后交由具体实现类自定义构建流程,使得同样的构建行为可以生产出不同的产品,分离了构建于表示,是构建产品灵活性大大增加。
使用场景
看到上面的模式定义内容,可以根据内容剥离出这个模式的使用场景。
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性。
- 隔离复杂对象的创建和使用,并使得相同的构建过程可以创建不同的产品。
建造者模式的优点
- 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建进行解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体建造者都是独立的,与其他的具体建造者无关,因此可以很方便的替换具体建造者或增加具体建造者,用户使用不同的具体建造者可以得到不同的产品对象,由于指挥者类针对抽象建造者编程,增加新的具体建造者无需修改原有类库的代码,系统扩展方便,符合开闭原则。在编写代码中,代码复用率尤为重要的。
- 用户可以更为精细的控制产品的创建过程,将复杂的产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
建造者模式的缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性较大,例如很多组成部分不相同,则不适用建造者模式,因此使用使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能需要很多具体建造者类实现这种变化,导致系统变得庞大,增加了系统的理解难度和运行成本。
建造者模式主要包含四种角色
- 抽象建造者(Builder):主要用于规范产品类的各个组成部分,并提供一个返回完整产品的接口。
- 具体建造者(Concrete Builder):实现抽象建造者规定的各个方法,返回一个组件好的具体产品。
- 产品(Product):构建相当复杂的类型,建造者最终创建的产品类型。
- 导演者(Director):指导建造者(Builder)以特定行为构建出产品,并将其返回给客户。
总结:理解了建造者模式四种角色,其实就已经掌握了建造者模式的真谛。建造者模式最终返回一个具体的构建复杂的产品;系统中产品可能只有一种类型或多种类型,但对某些产品族来说,它们具备相同的行为,因此对这些共性行为进行抽象,抽离出 抽象建造者(Builder);而对这些行为的具体构建过程,则交由具体建造者(Concrete Builder)负责,不同的具体建造者会构建出不同的表示的产品;而具体要构建出哪种产品,由导演者(Director)决定。导演者会选择不同的具体建造者,指导它构建出产品。
注意,也可以静态内部类实现建造者模式
事实上,在平常的代码中,我们通常都会忽略对象的复杂性,使用工厂模式创建对象,而不是建造者模式。正如上文所讲,工厂模式和建造者模式的作用都是用于创建一个产品对象,而工厂农商结构更加简洁直接(没有 Builder和Director)因此更常使用。
而建造者模式,我们更加习惯使用静态内部类的方式进行实现,即一个产品类内部自动带有一个具体建造者(Concrete Builder),由它负责产品的组装创建。不再需要抽象建造者(Builder)和导演者(Director),这样是的产品与构建之间的联系更加紧密,结构更加紧凑,同时使得建造者模式形式更加简洁。
示例代码
class Burger():
"""
主食类,价格名称
"""
name = ""
price = 0.0
def getPrice(self):
return self.price
def setPrice(self, price):
self.price = price
def getNmae(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):
return 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):
self.name = 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.gerName())
print("Snack: %s"%self.snack.gerName())
print("Beverage: %s"%self.beverage.gerName())
# 建造者
class orderBuilder():
"""
ordeBuilder 就是建造者模式中所谓的'建造者',
将订单的建造者与表示相分离,以达到解耦的目的。
在上面订单的构建过程中,如果将 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()
网友评论