本文简单介绍在 Swift 中用面向协议编程(POP)的方式实现模板方法。
模板方法是一种古老的设计模式,它使用一些抽象的操作定义一套算法或者流程,父类决定步骤,子类决定具体实现,当然父类可以提供一个默认实现。
在使用 Code + AutoLayout 写 UI 时,需要先添加子视图,再为子视图添加约束。由于 AutoLayout 是依赖于视图间的相互关系的,如果先为子视图添加约束再将其加到父视图上的话,程序将会崩溃。所以几乎每次在写 View 或者 ViewController 的时候我都会写这么几个方法:configViews
、addSubviews
、configConstraints
。这很糟糕,重复写一样的名字也是一种重复,这种事情应该交给自动补全,于是可以这样:
public protocol ViewTemplate {
var allSubviews: [UIView]? { get }
func configViews()
func addSubviews()
func configConstraints()
func additionalOperation()
}
public extension ViewTemplate {
var allSubviews: [UIView]? { return nil }
func additionalOperation() {}
func configViews() {
addSubviews()
configConstraints()
addtionalOperation()
}
}
public extension ViewTemplate where Self: UIView {
func addSubviews() {
allSubviews?.forEach(addSubview)
}
}
public extension ViewTemplate where Self: UIViewController {
func addSubviews() {
allSubviews?.forEach(view.addSubview)
}
}
然后就可以这样定义一个 View:
class DefaultView: UIView {
let defaultButton = UIButton()
let defaultIcon = UIImageView()
let defaultLabel = UILabel()
init() {
super.init(frame: .zero)
configViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension DefaultView: ViewTemplate {
var allSubviews: [UIView]? { return [defaultIcon, defaultLabel, defaultButton] }
func configConstraints() {
defaultLabel.snp_makeConstraints { (make) in
// ...
}
defaultIcon.snp_makeConstraints { (make) in
// ...
}
defaultButton.snp_makeConstraints { (make) in
// ...
}
}
func addtionalOperation() {
// ...
}
}
你不再需要考虑各个操作间的顺序,你获得了自动补全的支持,你的代码结构更加清晰。Hava fun~
网友评论