本文簡單介紹在 Swift 中用面向協(xié)議編程(POP)的方式實(shí)現(xiàn)模板方法谋旦。
模板方法是一種古老的設(shè)計(jì)模式,它使用一些抽象的操作定義一套算法或者流程演熟,父類決定步驟芒粹,子類決定具體實(shí)現(xiàn),當(dāng)然父類可以提供一個(gè)默認(rèn)實(shí)現(xiàn)座云。
在使用 Code + AutoLayout 寫 UI 時(shí),需要先添加子視圖,再為子視圖添加約束裸弦。由于 AutoLayout 是依賴于視圖間的相互關(guān)系的理疙,如果先為子視圖添加約束再將其加到父視圖上的話,程序?qū)罎⒃呶唷K詭缀趺看卧趯?View 或者 ViewController 的時(shí)候我都會寫這么幾個(gè)方法:configViews
、addSubviews
蹄皱、configConstraints
压鉴。這很糟糕,重復(fù)寫一樣的名字也是一種重復(fù)上鞠,這種事情應(yīng)該交給自動補(bǔ)全,于是可以這樣:
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)
}
}
然后就可以這樣定義一個(gè) 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() {
// ...
}
}
你不再需要考慮各個(gè)操作間的順序岭佳,你獲得了自動補(bǔ)全的支持,你的代碼結(jié)構(gòu)更加清晰叶洞。Hava fun~