iOS 小组件 - 全屏弹窗(策略模式重构)

1,514 阅读3分钟

2025.01.22 工作变动原因,故将一些工作期间Tapd内部写的Wiki文档转移到个人博客。

考虑到随着对于APP内部全屏弹窗的需求迭代,业务相关的代码在日积月累下会使基础功能类变得臃肿。

在此借着新版本开发的机会,对全屏弹窗基类基础功能使用策略模式重构并重新封装,使基础功能和业务分离、解耦。

一、重构之前的代码

如下图所示,原有的做法是使用 switch case 枚举管理业务类型,根据不同的 case 选择不同的业务进行视图初始化,导致业务类型庞大之后 YAYAlertView 类有了上千行的代码,显然是随着迭代的进行,以后维护的难度将会越来越大。

tapd_44062861_1683878516_639.png

二、策略模式优化具体实现

使用协议定义一个抽象方法,单独抽取业务代码,遵循协议,实现抽象方法。

protocol ShowAlertViewProtocol {
	/// 注入alertView的初始化方法
	func setupAlert();
}

在需要调用的地方,调用 YAYAlertViewsetup(_ 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 注入到基础功能类即可。

tapd_44062861_1683880520_341.png

以后只需要创建自己的业务视图,利用 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)
}

四、策略模式

策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。 以下是策略模式的结构图:

tapd_44062861_1683880965_618.png

策略模式的优点:
  • 你可以在运行时切换对象内的算法。
  • 你可以将算法的实现和使用算法的代码隔离开来。
  • 你可以使用组合来代替继承。
  • 开闭原则。 你无需对上下文进行修改就能够引入新的策略。
策略模式的缺点:
  • 如果你的算法极少发生改变, 那么没有任何理由引入新的类和接口。 使用该模式只会让程序过于复杂。
  • 客户端必须知晓策略间的不同——它需要选择合适的策略。
  • 许多现代编程语言支持函数类型功能, 允许你在一组匿名函数中实现不同版本的算法。 这样, 你使用这些函数的方式就和使用策略对象时完全相同, 无需借助额外的类和接口来保持代码简洁。

最最最后,完结撒花

告辞.jpeg