最近在看 Kingfisher 的源码的时候发现它将图片加载改成和 Android 中 Glide 一样的加载方式了。
- 原来的方式
// 函数
imageView.kf.setImage(
with: source,
placeholder: placeholder,
parsedOptions: options,
progressBlock: progressBlock,
completionHandler: resultHandler
)
- 现在的方式
KF.url(url)
.setProcessor(currentProcessor)
.serialize(as: .PNG)
.onSuccess { print($0) }
.onFailure { print($0) }
.set(to: cell.cellImageView)
一眼感觉起来还是下面的更舒服。
普通实现
以下代码为直接手敲,可能无法直接运行。
class Test {
private var p1: Int?
private var p2: Int?
// 其他属性...
private convenience init(_ builder: Builder) {
self.init()
p1 = builder.p1
p2 = builder.p2
// ...
}
class Builder {
var p1: Int?
var p2: Int?
func setP1(_ p1: Int?) -> Self {
self.p1 = p1
return self
}
func setP2(_ p2: Int?) -> Self {
self.p2 = p2
return self
}
@discardableResult
func build() -> Test {
Test(self)
}
}
}
// 使用
Test.Builder()
.setP1(1)
.setP2(2)
.build()
KF 的实现
enum KF {
static func url(_ url: String) -> Builder {
Builder(url)
}
class Builder {
// 若干个属性
convenience init(_ url: String) {
self.url = url
}
}
}
enum KF.Builder {
func set(to imageView: UIImageView) {
imageView.kf.xxxxx
}
}
// 其他属性的一些扩展
enum KF.Builder {
func placeholder(_ string: String) -> Self {
self.placeholder = placeholder
return self
}
}
实际上这个就是建造者模式的变种。
什么时候使用
- 当参数的数量超过 4 个,并且有若干个可选的;
- 当所有参数都需要准备完成之后,才可以进行下一步操作
什么时候不需要使用
- 当参数较少时,直接使用构造器,或者
set方法一点毛病也没有。当然考虑扩展性的话,也可以使用。 - 当调用函数时不需要所有参数都准备完成时,可以直接变成链式调用,而不需要建造者
let label = Label(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
.text("xxx")
.textColor(.red)
class Label: UILabel {
func text(_ text: String) -> Self {
self.text = text
return self
}
func textColor(_ textColor: UIColor) -> Self {
self.textColor = textColor
return self
}
}
说实话这样的写法有点 SwiftUI 的感觉。
引用
- zhuanlan.zhihu.com/p/58093669
kingfisher