iOS开发设计模式-工厂模式

工厂模式

核心:

解耦创建逻辑 · 多种子类 · 条件分支创建

思想及适用场景:

主要用于封装对象的创建逻辑,调用方只关心"我要什么",不关心"怎么造"。

当需要根据条件创建不同子类时尤其有用。

示例

swift 复制代码
// 产品协议
protocol Button {
    func render()
    func tap()
}

// 具体产品
struct IOSButton: Button {
    func render() { print("渲染 iOS 风格圆角按钮") }
    func tap()    { print("iOS 触感反馈") }
}

struct AndroidButton: Button {
    func render() { print("渲染 Material Design 按钮") }
    func tap()    { print("Android Ripple 动效") }
}

// 工厂 ------ 根据不同平台,决定创建哪种 Button
enum Platform { case iOS, android }

struct ButtonFactory {
    // 提供公共创建方法,传入不同条件/场景,返回协议对象 (调用方不需要知道具体类型)
    static func makeButton(for platform: Platform) -> Button {
        switch platform {
        case .iOS:     return IOSButton()
        case .android: return AndroidButton()
        }
    }
}

// 使用:调用方不需要知道具体类型
let btn = ButtonFactory.makeButton(for: .iOS)
btn.render()   // 渲染 iOS 风格圆角按钮
btn.tap()      // iOS 触感反馈

进阶:抽象工厂模式

思路:

在工厂模式基础上再抽象一层。普通工厂只生产一种产品,抽象工厂负责生产一族相关产品,保证同一工厂出来的产品风格一致,且调用方完全不依赖具体类。

核心区别一句话:工厂方法解决"造哪个",抽象工厂解决"造哪套"。

示例

  • 抽象产品协议
swift 复制代码
protocol Button {
    func render()
    func onTap()
}

protocol TextField {
    func render()
    func onInput(_ text: String)
}

// MARK: - iOS 具体产品
struct IOSButton: Button {
    func render()  { print("  🔵 渲染 iOS 圆角按钮") }
    func onTap()   { print("  📳 iOS Haptic 触感反馈") }
}

struct IOSTextField: TextField {
    func render()             { print("  🔵 渲染 iOS 下划线输入框") }
    func onInput(_ text: String) { print("  iOS 输入: \(text)") }
}

// MARK: - Android 具体产品
struct AndroidButton: Button {
    func render()  { print("  🟢 渲染 Material Design 按钮") }
    func onTap()   { print("  💧 Android Ripple 水波动效") }
}

struct AndroidTextField: TextField {
    func render()             { print("  🟢 渲染 Material 边框输入框") }
    func onInput(_ text: String) { print("  Android 输入: \(text)") }
}
  • 抽象工厂协议
scss 复制代码
protocol UIFactory {
    func makeButton() -> Button
    func makeTextField() -> TextField
}

// MARK: - 具体工厂(每个工厂只生产同一风格的产品族)

struct IOSFactory: UIFactory {
    func makeButton()    -> Button    { IOSButton() }
    func makeTextField() -> TextField { IOSTextField() }
}

struct AndroidFactory: UIFactory {
    func makeButton()    -> Button    { AndroidButton() }
    func makeTextField() -> TextField { AndroidTextField() }
}
  • 调用,客户端(只依赖抽象,不知道任何具体类型)
swift 复制代码
class LoginVC {
    private let button: Button
    private let textField: TextField

    // 注入工厂,由外部决定平台风格
    init(factory: UIFactory) {
        self.button    = factory.makeButton()
        self.textField = factory.makeTextField()
    }

    func show() {
        print("--- 渲染登录界面 ---")
        textField.render()
        textField.onInput("alice@example.com")
        button.render()
        button.onTap()
    }
}

// MARK: - 运行

print("=== iOS 平台 ===")
LoginVC(factory: IOSFactory()).show()

print("\n=== Android 平台 ===")
LoginVC(factory: AndroidFactory()).show()
  • 扩展

只需 新增 品类 和 工厂。不改 旧代码,不改调用方式(开闭原则),只需传递 新变量

scss 复制代码
// 新增 macOS 产品
struct MacOSButton: Button {
    func render() { print("  🖥 渲染 macOS NSButton") }
    func onTap()  { print("  🖱 macOS 点击事件") }
}

struct MacOSTextField: TextField {
    func render()                { print("  🖥 渲染 macOS NSTextField") }
    func onInput(_ text: String) { print("  macOS 输入: \(text)") }
}

// 新增工厂
struct MacOSFactory: UIFactory {
    func makeButton()    -> Button    { MacOSButton() }
    func makeTextField() -> TextField { MacOSTextField() }
}

// 使用 ------ LoginScreen 代码零修改
LoginScreen(factory: MacOSFactory()).show()

适用场景总结:

当系统需要独立于产品创建方式、且需要保证同一产品族的一致性时------比如跨平台 UI 套件、换肤主题、多数据库驱动(SQLite / CoreData / CloudKit)------抽象工厂是最合适的选择。

相关推荐
剪刀石头布啊6 小时前
vue-react为何要虚拟dom
前端
剪刀石头布啊6 小时前
ahooks常用的一些库,我们使用一下
前端
剪刀石头布啊6 小时前
从git更新本地提交记录到更新已经推送到远端记录
前端
Flynt8 小时前
axios 被投毒半年后,我把 npm 的"安全防线"实测了一遍:最信任的 SHA512 是安慰剂
前端·npm·node.js
excel9 小时前
Base62 和 Base64 有什么区别?
前端
风骏时光牛马10 小时前
大模型底层架构与AI源码深度剖析
前端
掘金挖土11 小时前
前端手摸手跑路之 AI 应用开发(九)
前端·后端
中文呀13 小时前
三维 GIS 离线缓存实战:逆向 CesiumOfflineCache,并亲手为它补上"自动更新"能力
前端
前进前进前进14 小时前
TRAE 全链路实战:做了一个警示牌一键生成器:纯 Canvas、单文件、零依赖
前端