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)------抽象工厂是最合适的选择。

相关推荐
陈随易5 小时前
在 VSCode 里,把项目一键部署到服务器
前端·后端·程序员
Highcharts.js5 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
To_OC6 小时前
我被 useState 坑了两次之后,终于把它的脾气摸透了
前端·javascript·react.js
鱼樱前端6 小时前
我用 Claude Code 后,编码效率翻 3 倍。但更值钱的是别的。
前端·后端·ai编程
_lucas6 小时前
给知识库网站接入AI问答
前端·ai编程·全栈
前端糕手7 小时前
前端面试题大全:JavaScript + Vue3 + React + TypeScript + 工程化 + 性能优化
前端
我不叫武8 小时前
一个用 Rust 写的离线编码查询桌面工具
前端
Web4Browser9 小时前
指纹浏览器 API 自动化怎么接:启动 Profile、获取 CDP 端点并连接自动化框架
前端·网络·typescript·自动化
Patrick_Wilson9 小时前
从 React 到 Flutter:写给前端的一张跨端知识地图
前端·flutter·react.js
颜酱9 小时前
06 | 把 meta_config 同步进 MySQL(生成阶段)
前端·人工智能·后端