「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战」
摘要
生成器模式可以用到有多个参数需要配置的对象中。可以将初始化和配置参数拆分开,达到分步创建对象的目的。同时也可以组合不同的配置参数,封装一个具体的对象初始化方法。
生成器是一种创建型设计模式,能使得你能够分步骤创建复杂对象。如何理解复杂的对象呢?
比如一个对象在创建的时候需要传递参数,传递的参数非常多(包含 4 或者 5 个参数或者以上的),就可以被称作是复杂的对象。怎么分步骤创建呢?
分步骤可以从这两方面入手:
- 把创建对象需要传递的参数拆分成一个个互不干扰的函数,使用函数来达到传递参数的目的,这里暂时称为参数函数。
- 通过组合的方式,把参数函数组合成不同功能的具体对象。
在 Swift 中,若要实现生成器模式,就需要使用 protocol
的方式。首先可以使用 protocol
来声明参数函数,这相当于一个接口类,现在创建有 3 个参数函数的接口类:
protocol Builder{
func attributesMethod1(_ attr1: String)
func attributesMethod2(_ attr2: Bool)
func attributesMethod3(_ attr3: String)
}
复制代码
现在创建一个具体的构建类,遵守 Builder
协议,分别实现这 3 个参数函数。
class ContereBuilder: Builder {
private var pro = Product()
func reset() {
pro = Product()
}
func attributesMethod1(_ attr1: String) {
pro.attri1 = attr1
print("set attri1 complete")
}
func attributesMethod2(_ attr2: Bool) {
pro.attri2 = attr2
print("set attri2 complete")
}
func attributesMethod3(_ attr3: String) {
pro.attri3 = attr3
print("set attri3 complete")
}
func retrieveProduct() -> Product {
let result = pro
reset()
return result
}
}
复制代码
在 ContereBuilder
类中定义一个 private
的 Product
对象,这 3 个参数函数就是给 Product
对象设置参数。其中也实现一个 reset()
函数,可以重新创建对象。同时创建一个获取对象的函数 retrieveProduct
,这个可以根据自己的需求处理,不用仿照这个处理。这里也定义 Product
类,声明 3 个变量,对应上面的参数函数。
class Product {
var attri1: String = ""
var attri2: Bool = false
var attri3: String = ""
}
复制代码
接下来就可以创建一个 Director
类,可以承担创建不同具体的对象,如下代码,buildProA(_:)
和 buildProB(_:isTrue:)
是分别对应不同的两个具体的对象,并在函数中配置对象的不同参数。后面就可以跟绝具体的业务生成不同的具体对象。
class Director {
private var builder: Builder?
func update(builder: Builder) {
self.builder = builder
}
func buildProA(_ str: String) {
builder?.attributesMethod1(str)
}
func buildProB(_ str: String, isTrue: Bool) {
builder?.attributesMethod2(isTrue)
builder?.attributesMethod3(str)
}
}
复制代码
到这里就已经完成生成器模式的所有处理了。下面代码实现的是创建一个 ProA 的具体对象,使用 buildProA
函数实现了。如果要创建其他具体对象,就使用其他构建对象的函数就好,比如使用 buildProB
函数。
class Client {
static func someMethod(director: Director) {
let builder = ContereBuilder()
director.update(builder: builder)
// 具体配置
director.buildProA("pro")
// 返回对象
let proA = builder.retrieveProduct()
print(proA)
}
}
复制代码
除了自己实现的生成具体对象的函数外,还可以使用遵守 Builder
协议的类自定义组合实现。
// 创建出新的具体对象
builder.attributesMethod1("123")
builder.attributesMethod2(true)
复制代码
生成器模式可以分步创建对象,延迟创建步骤或者递归运行创建步骤(类似链式实现)。并可以复用相同的创造代码生成不同类型的具体对象。这就可以把复杂的创建代码从业务逻辑中分离处理。但是这种模式需要增加很多类,因此代码整体复杂程度会增加一些。
题外话
设计模式比较抽象,需要多温习,多实践,才能很好吸收。所以本文会时时更新,力求把抽象说的更具体。没有考虑到的地方,可以评论区和我留言讨论。