客户端某些情况下,在页面上进行弹窗,比如升级提示,促销弹窗,以及新手引导等,本文将这些弹窗视为同一种类型,定义为PopView。
在展示弹窗时,会有很多限制,比如某个版本只弹一次,只在第一次登录后弹,多个弹窗互斥等。假设有需求:页面上有3种弹窗,view1,view2,view3,展示优先级依次降低。难免会有类似下面这样的代码:
// 假设优先显示view1
func showPopView() {
if view1.shouldShow:
view1.show()
else if view2.shouldShow:
view2.show()
else if view3.shouldShow:
view3.show()
}
...
func view1CloseCallBack() {
showPopView()
}
func view2CloseCallBack() {
showPopView()
}
这样的代码看起来很丑陋,而且如果showPopView与view的closeCallBack不在一起,别人来看代码的话,只看到了showPopView,会理解成优先展示一次弹窗。
一个简单的弹窗逻辑,出现这种问题的本质是什么呢?
是因为view1,view2,view3毫无关系,却在显示逻辑上强行加入了互斥与优先级。这种没有关联的对象,引入一个第三方对象来管理,可以解决这种问题。
再次体现了软件工程里,不变的真理,没有什么是引入一个间接对象解决不了的。
为此,新建一个PopviewManager,提供一个autoShow(view)的接口。
func showPopView() {
view1.priority = 1000
view2.priority = 100
view3.priority = 10
popviewManager.autoShow(view1)
popviewManager.autoShow(view2)
popviewManager.autoShow(view3)
}
这样逻辑就很清晰了,只在showPopView方法里完成了所有的弹窗展示逻辑。PopviewManager会根据待显示的views的优先级来安排展示,并且在一个弹窗关闭后展示优先级较低的弹窗。再也不用回调,再也不用if/else,完美!
后来想了想,这其实是一个中介者设计模式的的案例,通过一个对象来封装一组对象之间的交互逻辑。也验证了设计模式是不断的优秀实践的总结,并没有那么玄乎。也许平时你习以为常的一个设计,正是某种大名鼎鼎的设计模式。
实现细节上,因为PopView统一都在PopviewManager里控制展示,需要他们拥有统一的判断接口与展示接口,这里可以用协议来实现。PopviewManager还需要知道PopView的关闭事件,好启动下一个展示。
网友评论