策略模式与工厂模式的区别

news/2024/9/24 7:41:48/

策略模式与工厂模式的区别》

策略模式(Strategy Pattern)工厂模式(Factory Pattern) 都是常见的设计模式,虽然它们在设计目标上有一些相似之处,如解耦代码、增强扩展性,但它们的应用场景和解决的问题却是不同的。下面从多个角度详细对比它们的区别:

可以通过这两篇文章详细了解两种模式的原理 策略模式 工厂模式

1. 设计意图(目的不同)

  • 策略模式
    • 设计意图:用于在运行时根据不同的场景或条件,动态选择算法或行为。它的主要目标是将算法或行为的变化与使用它的客户端代码解耦,提供一种可以互换的算法或行为实现机制。
    • 应用场景:当一个对象需要执行某种行为,并且行为有多种实现方式时,策略模式允许程序动态选择不同的策略(算法)来执行该行为。
  • 工厂模式
    • 设计意图:工厂模式的主要目的是创建对象,它将对象的创建过程封装起来,使得创建对象的细节与使用对象的客户端解耦。工厂模式通常用于对象的实例化过程较为复杂的场景。
    • 应用场景:工厂模式适用于客户端只关心对象的接口,不关心具体对象如何创建的场景。工厂通过提供接口或父类,动态生成实例化对象。

2. 使用场景不同

  • 策略模式
    • 使用场景:在策略模式中,多个行为或算法可以根据条件动态选择。它解决了在运行时选择不同算法或行为的需求。例如:支付系统中根据不同支付方式选择相应的支付策略。
  • 工厂模式
    • 使用场景:工厂模式的核心在于创建对象,通过工厂类或方法来决定生成哪种对象。例如:数据库连接池中,工厂模式可以用于创建和管理不同类型的数据库连接。

3. 类结构与参与角色

策略模式类结构

  • 参与角色

    1. 策略接口(Strategy):定义了一组可互换的算法或行为。
    2. 具体策略类(ConcreteStrategy):实现了策略接口,定义了具体的算法或行为。
    3. 上下文类(Context):持有策略接口,并负责在运行时选择并执行某个策略。

    类图

在这里插入图片描述

工厂模式类结构:

  • 参与角色
    1. 工厂接口(Factory):定义创建对象的方法,通常返回一个接口类型或抽象类。
    2. 具体工厂类(ConcreteFactory):实现工厂接口,负责创建具体的对象。
    3. 产品接口(Product):定义创建出来的对象的公共接口。
    4. 具体产品类(ConcreteProduct):实现了产品接口,表示具体的对象。
  • 类图

在这里插入图片描述

4. 行为与对象创建的区别

  • 策略模式:核心目的是封装算法或行为,即将不同的算法或行为封装在具体的策略类中。运行时可以根据需要选择不同的策略,但策略模式本身不涉及对象的创建过程。
    • 行为驱动:它关注的是如何执行某个行为,并根据环境动态选择该行为的实现。
  • 工厂模式:核心目的是封装对象的创建,即将对象的创建过程放在工厂中,而不在客户端显式地创建对象。工厂模式的重点在于创建对象的方式。
    • 对象驱动:它关注的是如何创建某个对象,并根据需求生成不同的对象实例。

5. 是否动态切换策略

  • 策略模式:支持在运行时动态切换策略。上下文类可以根据条件或用户输入动态设置不同的策略对象。
    • 例子:在支付系统中,用户选择不同的支付方式(支付宝、信用卡、微信),策略模式会动态选择对应的支付策略。
  • 工厂模式:一旦创建了对象,对象不会动态变化。工厂负责生成对象后,该对象的行为和特性不会再改变。
    • 例子:数据库连接池中,工厂模式根据数据库类型创建连接对象,但连接对象一旦创建,它的行为和特性不会动态变化。

6. 实际案例应用对比

策略模式应用案例
  • 支付系统:在支付系统中,根据用户选择的支付方式(如支付宝、微信、信用卡等),选择不同的支付策略来完成支付。
  • 压缩算法:在文件压缩系统中,用户可以选择不同的压缩算法(如 ZIP、RAR、7Z),策略模式可以动态选择不同的压缩策略。
工厂模式应用案例
  • 日志系统:在日志系统中,根据配置文件或运行时的环境选择使用文件日志、数据库日志或控制台日志。工厂模式负责根据配置创建不同类型的日志对象。
  • 数据库连接池:根据应用程序所使用的数据库(如 MySQL、PostgreSQL),通过工厂模式动态创建不同的数据库连接对象。

7. 优缺点对比

策略模式

  • 优点
    1. 扩展性强:可以轻松添加新的策略类,而不影响已有代码,符合开闭原则。
    2. 代码简洁:避免了复杂的条件判断,通过选择不同的策略实现不同的行为。
    3. 可动态切换行为:允许在运行时选择不同的策略类,灵活应对多变的需求。
  • 缺点
    1. 增加类的数量:每种策略都需要一个具体类,增加了系统类的数量。
    2. 客户端需要了解策略:客户端需要了解并选择合适的策略,这对使用者提出了更高的要求。

工厂模式:

  • 优点
    1. 解耦对象创建过程:将对象的创建与使用分离,客户端不需要关心具体对象如何创建。
    2. 减少重复代码:避免了在多个地方创建对象的重复代码,统一管理对象的创建过程。
    3. 符合开闭原则:当添加新的对象时,可以通过扩展工厂类来实现,不影响已有代码。
  • 缺点
    1. 可能导致类膨胀:如果系统中有许多具体产品和工厂,可能导致类的数量急剧增加。
    2. 复杂性增加:虽然减少了客户端的复杂性,但工厂模式增加了系统的结构复杂性,尤其是工厂方法模式和抽象工厂模式。

8.总结:

  • 策略模式 侧重于封装算法或行为,并允许根据运行时条件动态选择不同的策略。它适用于需要在运行时根据场景动态切换行为的情况。
  • 工厂模式 侧重于创建对象,隐藏对象创建的复杂性,使得客户端只关心使用对象,而不需要关心如何创建对象。它适用于创建对象过程较为复杂的情况。
  • 示例总结
    • 如果你想在一个支付系统中动态选择支付方式,那么你应该使用 策略模式
    • 如果你在一个应用中需要根据数据库类型来生成不同的数据库连接对象,那么你应该使用 工厂模式

http://www.ppmy.cn/news/1529713.html

相关文章

STM32G474的SPI工作在从机模式

STM32G474的SPI工作在从机模式,我们令SPI1工作在主机模式,SPI2工作在从机模式中,实现数据数据互传。本测试只讲解SPI一主一从通讯,至于一主多从,程序中有说明。 SPI1外设用作主机,其接口:将SPI1…

UE5学习笔记22-武器瞄准和武器自动开火

0、一些疑问的记录 1.UUserWidget类和AHUD类的区别。两者都是关于界面显示的类。 实践: 想让界面和用户有交互使用UUserWidget,如果不要交互只是显示使用AHUD类,例如使用UUserWidget类制作开始界面,游戏开始,游戏设置&…

微服务--Gateway网关

在微服务架构中,Gateway(网关)是一个至关重要的组件,它扮演着多种关键角色,包括路由、负载均衡、安全控制、监控和日志记录等。 Gateway网关的作用 统一访问入口: Gateway作为微服务的统一入口&#xff0c…

【LeetCode】【C++】27. 移除元素 80.删除有序数组中的重复项Ⅱ

27. 移除元素 题目描述 详见LeetCode 27. 移除元素。 这是一道特别水的题,但是我第一时间没有想到正确的解答思路。 题目描述可以简述为,给定数组nums和元素val,原地删除nums中等于val的元素,并返回nums中不等于val元素的个数…

新提案:C++将变得内存安全

革命性的提案:C 将添加借用检查、生命周期、mut、sendsync 在遭受内存安全棒的打击两年后,C 社区发布了一项提案,以帮助开发人员编写更不容易受到攻击的代码。 Safe C 扩展提案旨在解决易受攻击的编程语言的致命弱点,即确保代码…

json Date格式化时间偏差8小时,而@JsonFormat注解有无法动态指定时区,如何解决?

use this method to set timezone and replace JsonFormat(pattern “yyyy-MM-dd HH:mm:ss”, timezone“GMT8”) (1)Model field JSONField(format DateTimeJsonFormatSerializer.TIME_FMT)//fastjson,JSON.toJSONString()JsonSerialize(using DateTimeJsonFormatSerializ…

如何从格式化的笔记本电脑或台式机中恢复照片

您想学习如何从已格式化的笔记本电脑或台式机中恢复已删除的照片吗?这篇文章解释了如何使用最佳格式的照片恢复软件来做到这一点。您可以通过简单的步骤格式化计算机后恢复已删除的图像。 将照片保存在笔记本电脑或 PC 硬盘上是很常见的。与相机存储卡和 USB 闪存驱…

排序----希尔排序

void ShellSort(int* a, int n) {int gap n;while (gap > 1){// 1保证最后一个gap一定是1// gap > 1时是预排序// gap 1时是插入排序gap gap / 3 1;for (size_t i 0; i < n - gap; i){int end i;int tmp a[end gap];while (end > 0){if (tmp < a[end]){…