@resultBuilder
结果构造器,以注释器的方式优雅的实现工厂模式。
类:
struct Factory {
var name: String
}
一、buildBlock(_:)
@resultBuilder
必须实现的方法,是结果构造器的主体方法;
@resultBuilder
struct FactoryBuilder {
static func buildBlock(_ singles: Factory...) -> [Factory] {
return singles
}
static func buildBlock(_ components: String...) -> [Factory] {
return components.map({ Factory(name: $0) })
}
}
用法:
@FactoryBuilder
static func factories() -> [Factory] {
Factory(name: "option 1")
Factory(name: "option 2")
}
@FactoryBuilder
static func factoriesUseString() -> [Factory] {
"option 1"
"option 2"
}
二、buildEither(first:)
、buildEither(second:)
此二方法需同时实现,主要用于实现if-else
、switch
条件语句,如:
static func buildEither(first component: [Factory]) -> [Factory] {
component
}
static func buildEither(second component: [Factory]) -> [Factory] {
component
}
用法:
@FactoryBuilder
static func factories() -> [Factory] {
if flag1 == 0 {
Factory(name: "option 1")
} else {
Factory(name: "option 2")
}
}
三、buildArray(_:)
此方法用于实现for、while等循环语句,如:
static func buildArray(_ components: [[Factory]]) -> [Factory] {
components.flatMap({ $0 })
}
使用时可以发现,
Cannot pass array of type '[Factory]' as variadic arguments of type 'Factory'
分析后可以看到,需要实现一个可以接收数组的buildBlock(_:)
方法
如:
static func buildBlock(_ components: [Factory]) -> [Factory] {
return components
}
但实际操作下来,使用协议统一传参是最好的方案,如:
protocol Factoryer {
var asFactories: [Factory] { get }
}
@resultBuilder
struct FactoryBuilder {
static func buildBlock(_ singles: Factoryer...) -> [Factory] {
return singles.flatMap({ $0.asFactories })
}
static func buildArray(_ components: [[Factory]]) -> [Factory] {
return components.flatMap({ $0 })
}
}
用法:
@FactoryBuilder
static func factoriesUseArray() -> [Factory] {
for i in 0..<3 {
Factory(name: "option \(i)")
}
}
四、buildOptional(_:)
该方法主要用于实现可选项。如:
-
Factory
对象非一定存在
let flag1: Int = 0
if flag1 == 0 {
Factory(name: "option 1")
}
-
Factory
对象非一定存在,但存在else if
需要注意的是,如果有二种以上的结果,需要同时实现buildEither(first:)
、buildEither(second:)
。如:
let flag1: Int = 0
if flag1 == 0 {
Factory(name: "option 1")
} else if flag1 == 1 {
Factory(name: "option 2")
}
五、buildExpression(_:)
buildExpression(_:)
会在buildBlock(_:)
之前执行。
它允许结果构建器区分表达式类型和组件类型,为语句表达式提供上下文类型信息。如:
static func buildExpression(_ expression: String...) -> [Factory] {
return expression.map({ Factory(name: $0) })
}
static func buildExpression(_ expression: Factoryer...) -> [Factory] {
return expression.flatMap({ $0.asFactories })
}
用法:
@FactoryBuilder
static func factoriesUseString() -> [Factory] {
"option 1"
"option 2"
"option 3"
}
六、buildLimitedAvailability(_:)
用于将 buildBlock(_:)
在受限环境下(例如if #available
)产生的部分结果转化为可适合任何环境的结果,以提高 API 的兼容性。
七、buildFinalResult(_:)
用于对最外层的 buildBlock(_:)
结果的再包装。例如,让结果构建器隐藏一些它并不想对外的类型(转换成可对外的类型)。
网友评论