设计模式(三)生成器模式

「这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

摘要

生成器模式可以用到有多个参数需要配置的对象中。可以将初始化和配置参数拆分开,达到分步创建对象的目的。同时也可以组合不同的配置参数,封装一个具体的对象初始化方法。

生成器是一种创建型设计模式,能使得你能够分步骤创建复杂对象。如何理解复杂的对象呢?

比如一个对象在创建的时候需要传递参数,传递的参数非常多(包含 4 或者 5 个参数或者以上的),就可以被称作是复杂的对象。怎么分步骤创建呢?

分步骤可以从这两方面入手:

  1. 把创建对象需要传递的参数拆分成一个个互不干扰的函数,使用函数来达到传递参数的目的,这里暂时称为参数函数
  2. 通过组合的方式,把参数函数组合成不同功能的具体对象。

在 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 类中定义一个 privateProduct 对象,这 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)
复制代码

生成器模式可以分步创建对象,延迟创建步骤或者递归运行创建步骤(类似链式实现)。并可以复用相同的创造代码生成不同类型的具体对象。这就可以把复杂的创建代码从业务逻辑中分离处理。但是这种模式需要增加很多类,因此代码整体复杂程度会增加一些。

题外话

设计模式比较抽象,需要多温习,多实践,才能很好吸收。所以本文会时时更新,力求把抽象说的更具体。没有考虑到的地方,可以评论区和我留言讨论。

おすすめ

転載: juejin.im/post/7034124863769935879