当前位置: 首页 > article >正文

iOS中的设计模式(三)- 工厂方法

引言

几乎在每个用面向对象语言开发的应用程序中,都能见到工厂方法模式的身影。它是 抽象工厂模式 的核心组成部分。通过重载抽象工厂父类中定义的工厂方法,各种具体工厂能够创建属于自己的对象。

在工厂方法模式中,生产者 本身并不一定是抽象工厂,它可以是任意类。关键在于不直接创建对象实例,而是通过工厂方法创建对象,并以抽象类型返回。这种设计使得代码对具体类的依赖降低,便于扩展和维护。

什么是工厂方法

工厂方法也称为虚拟构造器。它适用于这种情况:一个类无法渔区需要生成那个类型的对象,像让其子类来指定所生成的对象。

抽象的Product定义了工厂方法创建的对象的接口。而实际的产品ConcreteProduct实现了Product接口。Creator定义了返回Product对象的工厂方法。它也可以为工厂方法定义一个默认的实现。返回一个默认的ConcrereProduct对象。Creator的其它操作可以调用此工程方法来创建Product对象。ConcrereCreator是Creator的子类。它重载了工厂方法,以返回ConcreteProduct的实例。

工厂方法的最初定义就是专注于让子类决定创建什么对象。

什么时候使用工厂方法

工厂方法模式特别适合以下场景:

  1. 当类不知道需要实例化的具体对象时(例如,使用协议或基类表示的对象)。
  2. 需要将对象的创建逻辑与使用逻辑解耦时(例如,在网络层或数据解析层)。
  3. 需要支持多种对象类型,并且类型会随需求变化时

与简单工厂模式相比,工厂方法提供了更大的灵活性;与抽象工厂模式相比,它更关注单个对象的创建逻辑而非一组对象。

通过工厂方法模式,你的代码将能够以更高的可扩展性和灵活性应对变化,为复杂应用提供强大的支持。

如何使用工厂方法

我们以实际开发中适配深色模式和浅色模式为例, 这个场景非常适合创建多个具体的工厂。每个模式都可以有自己独特的风格和组件。我们可以通过每个工厂为特定模式创建适配的UI组件。

具体代码如下:

首先是定义组件的接口(Product)。

protocol ThemeComponent {
    func render()
}

接着我们来定义具体的组件,他们需要遵循ThemeComponent并实现ThemeComponent中定义的方法。

class LightButton: ThemeComponent {
    func render() {
        print("Rendering a light-themed button.")
    }
}

class DarkButton: ThemeComponent {
    func render() {
        print("Rendering a dark-themed button.")
    }
}

class LightTextField: ThemeComponent {
    func render() {
        print("Rendering a light-themed text field.")
    }
}

class DarkTextField: ThemeComponent {
    func render() {
        print("Rendering a dark-themed text field.")
    }
}

接下来我们需要定义工厂接口(Creator),来创建产品。

protocol ThemeFactory {
    func createButton() -> ThemeComponent
    func createTextField() -> ThemeComponent
}

最后遵循Creator来定义具体的工厂(ConcreteCreator),创建具体的产品。

class LightThemeFactory: ThemeFactory {
    func createButton() -> ThemeComponent {
        return LightButton()
    }
    func createTextField() -> ThemeComponent {
        return LightTextField()
    }
}

class DarkThemeFactory: ThemeFactory {
    func createButton() -> ThemeComponent {
        return DarkButton()
    }
    func createTextField() -> ThemeComponent {
        return DarkTextField()
    }
}

在代码中使用工厂时,只需要根据主题模式来创建不同的工厂,而创建具体组件的任务交给工厂即可。

 // 假设通过用户设置或系统获取主题
    let isDarkMode = true
    let factory: ThemeFactory = isDarkMode ? DarkThemeFactory() : LightThemeFactory()

    // 使用工厂创建组件
    let button = factory.createButton()
    let textField = factory.createTextField()

    // 渲染组件
    button.render()
    textField.render()

当isDarkModel == true时:

Rendering a dark-themed button.
Rendering a dark-themed text field.

当isDarkModel == false时:

Rendering a light-themed button.
Rendering a light-themed text field.

工厂方法在实际项目中的使用

在多主题的应用中,通常我们都会使用到工厂方法,通过将对象的创建与使用解耦,来根据不同的需求灵活地生成合适的对象。

首先定义一个主题协议,里面会定义各种颜色、图片或者是UI组件,但不需要提供实现:

public protocol MWThemeProtocol  {
    
    /// 主题颜色
    var themeColor:UIColor { get }
    /// 主要容器背景颜色
    var containerBgColor:UIColor { get }
    /// 次要容器背景颜色
    var secondaryContainerBgColor:UIColor { get }
    /// 主要文字颜色
    var primaryTextColor:UIColor { get }
 ...
}

接下来创建一个具体的工厂来遵守该协议,并实现所有方法,返回该工厂指定样式的内容:

public class MWThemeNormalFactory: MWThemeProtocol {
    /// 主题颜色
    public var themeColor: UIColor {
        return UIColor.red
    }
    /// 主要容器背景颜色
    public var containerBgColor: UIColor {
        return UIColor.white
    }
    /// 次要容器背景颜色
    public var secondaryContainerBgColor: UIColor {
        return .wm_hex("#EFF1F5")
    }
    /// 主要文本颜色
    public var primaryTextColor: UIColor {
       return .wm_hex("#11111B")
   }
    /// 次要文本颗色
    public var secondaryTextColor: UIColor {
        return .wm_hex("#6C7086")
    }
...
}

创建另外一个工厂,也遵循该协议并实现所有方法,返回该工厂指定样式的内容:

public class MWThemeDarkFactory: MWThemeProtocol {
    
    /// 主题颜色
    public var themeColor: UIColor {
        return UIColor.red
    }
    /// 主要容器背景颜色
    public var containerBgColor: UIColor {
        return .wm_hex("#11111B")
    }
    /// 次要容器背景颜色
    public var secondaryContainerBgColor: UIColor {
        return .wm_hex("#1E1E2E")
    }
    /// 主要文本颜色
    public var primaryTextColor: UIColor {
       return .wm_hex("#FFFFFF")
   }
    /// 次要文本颗色
    public var secondaryTextColor: UIColor {
        return .wm_hex("#BCC0CC")
    }
...
}

一个多主题应用的主要主题系统的核心部分就构建完成了,接下来我们只需要根据不同的主题来创建不同的工厂,工厂内部会创建该主题对应的UI元素。

public class MWThemeHelper: NSObject {
    
    /// 创建主题工厂
    public static var themeFactory:MWThemeProtocol = MWThemeNormalFactory()
    
    /// 启动设置主题
    public static func setupTheme() {
        // 读取系统深色模式设置
        
    }
    
    /// 更新主题
    private static func updateTheme(themeType:MWThemeType) {
        switch themeType {
        case .light:
            themeFactory = MWThemeNormalFactory()
        case .dark:
            themeFactory = MWThemeDarkFactory()
        }
    }
    ....
}

结语

在多主题的应用中,工厂方法模式显得尤为重要。通过将对象的创建与使用解耦,我们能够根据不同的需求和情境灵活地生成合适的对象,尤其是在需要支持多个界面主题时。工厂方法不仅能帮助我们维持代码的清晰和扩展性,还能有效应对不断变化的需求。最重要的是,灵活使用工厂方法,可以提高代码的可维护性和可重用性,从而打造更加高效和可靠的应用程序。在设计时,将工厂方法与不同的需求场景结合,可以让我们的应用更具适应性,且易于扩展。


http://www.kler.cn/a/512258.html

相关文章:

  • 详解构造函数和析构函数
  • 【分类】【损失函数】处理类别不平衡:CEFL 和 CEFL2 损失函数的实现与应用
  • 【PyCharm】连接 Git
  • Web前端第一次作业
  • PHP 8.4 安装和升级指南
  • javaEE初阶————多线程初阶(2)
  • 分布式系统架构7:本地缓存
  • CSS 实体
  • 第11章:Python TDD实现货币类加法运算初步
  • 深入HDFS——HA和QJM
  • 4.1 AI 大模型应用最佳实践:如何提升 GPT 模型使用效率与质量
  • MySQL多表查询练习
  • 数据库性能优化(sql优化)_SQL执行计划01_yxy
  • 【数据结构篇】顺序表 超详细
  • 从一到无穷大 #42:ClickHouse - 极致工程优化的Lightning Fast Analytics
  • vue3+vite+ts+router4+Pinia+Axios+sass 从0到1搭建
  • Sam Altman亲自确认:o3-mini即将上线!GPT和o系列模型合并!
  • Halcon 3D基础知识及常用函数
  • 基于本地消息表实现分布式事务
  • JAVAweb学习日记(五) SpringBootWeb
  • Vue+Element-ui 中 使用el-table 设置表格单元格 (el -table-column) 保留空格和换行
  • ASP .NET Core 学习(.NET9)配置接口访问路由
  • 从CentOS到龙蜥:企业级Linux迁移实践记录(容器与应用)
  • 25届合肥工业大学自动化考研复试攻略
  • 大型语言模型(LLM)在算法设计中的系统性综述
  • MySQL 数据库的备份和恢复(Linux)