2025.01.22 工作变动原因,故将一些工作期间Tapd内部写的Wiki文档转移到个人博客。
考虑到随着对于APP内部全屏弹窗的需求迭代,业务相关的代码在日积月累下会使基础功能类变得臃肿。
在此借着新版本开发的机会,对全屏弹窗基类基础功能使用策略模式重构并重新封装,使基础功能和业务分离、解耦。
一、重构之前的代码
如下图所示,原有的做法是使用 switch case 枚举管理业务类型,根据不同的 case 选择不同的业务进行视图初始化,导致业务类型庞大之后 YAYAlertView 类有了上千行的代码,显然是随着迭代的进行,以后维护的难度将会越来越大。
二、策略模式优化具体实现
使用协议定义一个抽象方法,单独抽取业务代码,遵循协议,实现抽象方法。
protocol ShowAlertViewProtocol {
/// 注入alertView的初始化方法
func setupAlert();
}
在需要调用的地方,调用 YAYAlertView 的 setup(_ showAlertView: ShowAlertViewProtocol, needMaskAction: Bool) 方法,遵循 依赖倒置 原则注入业务View。
例子:
// 弹窗注入初始化
func setup(_ showAlertView: ShowAlertViewProtocol, needMaskAction: Bool) {
if let alertView = showAlertView as? UIView {
alertView.frame = self.bounds
addSubview(alertView)
// 调用协议方法,实现子类弹窗初始化布局
showAlertView.setupAlert()
}
// 添加遮罩点击
if needMaskAction {
maskControl.addTarget(self, action: #selector(close), for: .touchUpInside)
}
}
三、最终效果
使用策略模式优化之后的 YAYAlertView 只有146行代码,且增加新的业务需求时不会修改到功能代码,大大增强了代码的可维护性和稳定性,降低了耦合。
以下是重构之后的文件结构,每一个业务只需要在 Views 文件夹下增添自己的业务视图即可。
例如,下图的 “版本更新弹窗”,添加 YAYAppVersionInfoModel 管理数据模型,添加 YAYNewVersionAlertView 业务视图到 Views 文件夹下,最后把 YAYNewVersionAlertView 注入到基础功能类即可。
以后只需要创建自己的业务视图,利用 alertView.setup() 方法去注入业务视图到基础功能即可
最终执行效果:
// 业务调用全屏弹窗的方法
func setupNewVersion() {
// 基础弹窗
let alertView = YAYAlertView(frame: CGRect(x: (screenWidth - 310)/2, y: (screenHeight - 333)/2, width: 310, height: 333))
// 更新弹窗,业务视图
let newVersionView = YAYNewVersionAlertView()
// 业务弹窗注入基础功能
alertView.setup(newVersionView, needMaskAction: false)
}
四、策略模式
策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。 以下是策略模式的结构图:
策略模式的优点:
- 你可以在运行时切换对象内的算法。
- 你可以将算法的实现和使用算法的代码隔离开来。
- 你可以使用组合来代替继承。
- 开闭原则。 你无需对上下文进行修改就能够引入新的策略。
策略模式的缺点:
- 如果你的算法极少发生改变, 那么没有任何理由引入新的类和接口。 使用该模式只会让程序过于复杂。
- 客户端必须知晓策略间的不同——它需要选择合适的策略。
- 许多现代编程语言支持函数类型功能, 允许你在一组匿名函数中实现不同版本的算法。 这样, 你使用这些函数的方式就和使用策略对象时完全相同, 无需借助额外的类和接口来保持代码简洁。