持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
前言
在面向对象的开发过程中,其实咱们或多或少的都接触过一些设计模式,可能知道或不知道其对应的名称,也不知道其具体使用场景,今天咱们就来说说几种常见的设计模式,帮助你们在开发过程中,更加得心应手。
正文
建造者模式也叫生成器模式,它用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”创建不同的对象。
例子:
我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个主食(Main coures)和一杯冷饮(Cold drink)。
主食(Main coures)可以是牛排(steak)或汉堡(Burger),它们是在餐盘中。
冷饮(Cold drink)可以是可乐(cola)或无糖可乐(Diet Coke),它们是装在瓶子中。
我们将创建一个表示食物条目(比如主食和冷饮)的 Item 接口和实现 Item 的接口的实体类,以及一个表示食物包装的 Packing 接口和实现接口的实体类。主食是放在餐盘中,冷饮装在瓶子里。
然后我们创建 Meal 类,和一个创建不同类型的 Meal 对象的 MealBuilder。
step 1 先创建食物包装的 protocol
/// 食物包装
protocol Packing {
var pack: String {get}
}
class Box: Packing {
var pack: String {"餐盘"}
}
class Bottle: Packing {
var pack: String {"瓶子"}
}
step 2 创建食物具备哪些属性的 protocol
/// 食物条目
protocol Item {
var name: String {get}
var packing: Packing { get }
var price: Double { get }
}
step 3 创建主食
class Main_coures: Item {
var packing: Packing { Box() }
var price: Double { 10 }
var name: String {"主食"}
}
class Steak: Main_coures {
override var price: Double { 50 }
override var name: String {"牛排"}
}
class Burger: Main_coures {
override var price: Double { 25 }
override var name: String { "汉堡"}
}
step 4 创建冷饮
class ColdDrink: Item {
var packing: Packing { Bottle() }
var price: Double { 15 }
var name: String { "冷饮" }
}
class Cola: ColdDrink {
override var price: Double { 30 }
override var name: String { "可乐" }
}
class Diet_Coke : ColdDrink {
override var price: Double { 35 }
override var name: String { "无糖可乐"}
}
step 5 构建套餐
/// 套餐
class Meal {
var items: [Item] = []
func add(item: Item) {
items.append(item)
}
func getCost() -> Double {
return items.reduce(0) { (total, item) -> Double in
return total + item.price
}
}
func showItems() {
items.forEach { (item) in
print("条目:(item.name), 打包:(item.packing.pack), 价格:(item.price)")
}
}
}
/// 创建 Meal 对象
class MealBuilder {
func makeSteakMeal() -> Meal {
let meal = Meal()
meal.add(item: Steak())
meal.add(item: Cola())
return meal
}
func makeBurgerMeal() -> Meal {
let meal = Meal()
meal.add(item: Burger())
meal.add(item: Diet_Coke())
return meal
}
}
let mealBuilder = MealBuilder()
print("牛排套餐")
let vegMal = mealBuilder.makeSteakMeal()
vegMal.showItems()
print("总计:(vegMal.getCost())\n")
print("汉堡套餐")
let noVegMal = mealBuilder.makeBurgerMeal()
noVegMal.showItems()
print("总计:(noVegMal.getCost())")
最后输出:
牛排套餐
条目:牛排, 打包:纸盒, 价格:50.0
条目:可乐, 打包:瓶子, 价格:35.0
总计:85.0
汉堡套餐 条目:汉堡, 打包:纸盒, 价格:25.0
条目:无糖可乐, 打包:瓶子, 价格:30.0
总计:55.0
结语
建造者模式适合有多个复杂属性的对象,就像例子中的套餐一样。
优点:对复杂对象的创建细节进行隔离,方便使用者调用,减少了bug。
缺点:代码重复,需要对每种情况进行处理,有一定的维护成本。
扩展阅读 下面还有其他模式