设计模式之工厂方法模式

2023-11-01

工厂方法模式

根据简单工厂模式的案例可知,如果我们想要添加一种立方运算,只需要创建一个立方运算类继承运算类,然后在工厂类中添加一个case分支用于逻辑判断,问题在于,我们在进行功能扩展的同时,也修改了工厂类中的代码,这很明显违背了开放-封闭原则,于是工厂方法模式应运而生。

UML类图:
在这里插入图片描述

工厂模式:定义一个创建对象的工厂类,为每一种需要创建对象的类创建一个相应的具体工厂类来继承该工厂类,如有A类,B类,C类,那我们就创建3个具体工厂类继承工厂类分别用于创建A类对象、B类对象和C类对象。在客户端,根据逻辑判断出我们需要创建什么对象,先创建相应的工厂对象,然后通过相应的工厂对象调用其中的成员函数创建我们需要的对象,比如我们想要创建A类对象,就需要先创建相应的A类工厂对象,然后通过A类工厂对象调用其成员函数创建出A类对象。

#include<iostream>
using namespace std;

class Base
{

};

class A:public Base
{

};

class B:public Base
{

};

//工厂类
class Factory
{
public:
	virtual Base* createConcrete() { return nullptr; };
};

//具体工厂类
class Afactory:public Factory
{
public:
	Base* createConcrete() override
	{
		cout << "A类对象被创建" << endl;
		return new A();
	}
};

class Bfactory:public Factory
{
public:
	Base* createConcrete()
	{
		cout << "B类对象被创建" << endl;
		return new B();
	}
};

int main()
{
	//依据逻辑判断需要创建A类对象
	//先创建相应的工厂对象
	//如果需要更换对象,即创建B类对象,只需要把Afactory更换为Bfactory即可
	Factory* factory = new Afactory();
	//然后通过工厂对象调用其成员函数创建我们需要的对象
	Base* base = factory->createConcrete();
}

这样,当我需要添加立方运算时,只需要添加一个立方运算类继承运算类,再添加一个相应的工厂类继承抽象工厂类,而无需对原有工厂类进行修改,这样就完全符合开放-封闭原则的精神。

在这里插入图片描述
但其实仔细观察就会发现,工厂模式把简单工厂内部的选择判断逻辑移到了客户端代码来进行,你想要增加功能,本来是改工厂类的,现在是要修改客户端。

优点:
工厂模式既克服了简单工厂模式违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点,使得要更换对象时,不需要大的改动就能实现,降低了客户端程序与产品对象的耦合。

缺点:

  • 每增加一个产品类,就需要增加一个相应的工厂类,增加了额外的开发量。
  • 将简单工厂模式中工厂类中要创建什么对象的逻辑判断移到了客户端程序,增加功能的时候需要修改客户端。

使用场景:

  • 首先,工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是需要慎重地考虑是否要增加一个工厂类进行管理,增加代码的复杂度。
  • 其次,需要灵活的、可扩展的框架时,可以考虑采用工厂模式。万物皆对象,那万物也就皆产品类,例如需要设计一个连接邮件服务器的框架,有三种网络协议可供选择:POP3、IMAP、HTTP,我们就可以把这三种连接方法作为产品类,定义一个工厂类如IConnectMail,然后创建3个具体的工厂类继承工厂类用于创建3种产品类的对象,再按照不同的传入条件,创建不同的产品对象,选择不同的连接方式。如此设计,可以做到完美的扩展,如某些邮件服务器提供了WebService接口,很好,我们只要增加一个产品类和相应的工厂类就可以了。
  • 再次,工厂方法模式可以用在异构项目中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之工厂方法模式 的相关文章

  • dlopen 或 dlclose 未调用信号处理程序

    我在随机时间内收到分段错误 我注册了信号 但发生分段错误时未调用信号处理程序 include
  • 二元运算符重载、隐式类型转换

    class my bool private bool value public my bool bool value value value explicit operator bool return value friend my boo
  • Spring 非托管 bean 的依赖注入

    我有一个非托管的 JPA 域类 它是通过实例化的new操作员 UserAccount account new UserAccount userRepository save account In my UserAccount类 我有一个be
  • 如何告诉 Eclipse 忽略 Ant build.xml 中的错误?

    我有一个使用 Maven 构建的 Eclipse 项目 并且我在 Eclipse 中使用 m2eclipse 插件来获得 Maven 支持 然而这个项目还包含一个build xml它并不用于实际构建项目 而只是用于编写脚本功能 作为项目开发
  • 如何在 Struts 2 中访问 OGNL 跟踪评估?

    有人告诉我要优化网络应用程序 为此 我使用JProfiler https www ej technologies com products jprofiler overview html 我注意到很大一部分响应时间都花在了表示层上 特别是当
  • 谷歌基准迭代的意义是什么?

    我正在使用 Google Benchmark 来测量某些代码的执行时间 例如 我编写了以下代码来测量其执行时间性能 include
  • 具有多重继承的不明确基数

    我正在尝试在一个大库中编写一些类的子类 我收到 基础不明确 错误 这是该问题的一个可编译示例 include
  • 在JAVA中将数据写入.txt文件?

    我想知道是否是在JAVA中将计算的数据写入文本文件 我的 JAVA 代码是一个基于 GUI 的 gpa 计算器 我只想添加一个 JButton 和 ActionListener 它将类名 GPA 点和计算出的 GPA 写入 txt 文件 这
  • 阻止用户取消选择列表框中的项目?

    我有一个列表框 里面有很多项目 用户可以单击某个项目来编辑其内容 如何防止用户取消选择所有项目 即 用户不应该无法选择任何内容 您的情况缺少一个案例 即清除列表后 您将选择列表中不再存在的项目 我通过添加额外的检查来解决这个问题 var l
  • 访问结构向量

    我有一个结构 struct OutputStore int myINT string mySTRING 如果我创建一个 OutputStore 类型的数组 如下所示 OutputStore OutputFileData new Output
  • 如何修改 edmx 的默认代码生成策略?

    我想修改默认的代码生成策略 该怎么做 我只是想修改类名 lt code Escape container gt to Entities并将默认连接字符串更改为name Default 我不想为该项目创建模板文件 我想编辑它以便它可以在全球范
  • 在 Struts 2 中使用单个文件标签上传多个文件

    我想使用单个 Struts 2 文件标签上传多个文件 就像在 Gmail 中一样 我们使用 CTRL 键来选择多个文件来附加多个文件 我知道如何上传多个文件 但我想使用单个文件标签 我在一个小画廊应用程序中上传多个文件 如果您的操作已设置为
  • 如何使用JSqlParser向sql添加where条件?

    我想用JSqlParser向sql添加where条件 例如 Before select from test table where a 1 group by c After select from test table where a 1
  • 为什么 C++ 元组如此奇怪?

    我通常创建自定义structs将不同类型的值分组在一起时 这通常很好 而且我个人发现命名成员访问更容易阅读 但我想创建一个更通用的 API 在其他语言中广泛使用元组后 我想返回类型的值std tuple但发现它们在 C 中使用比在其他语言中
  • 如何组织课程、课程包[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 您如何决定包名称应该是什么以及什么类应该放入哪个包中 我正在开发一个项目 在该项目中 我不断添加 删除类 并且不确定我是否需要一个新包 或者应该将其添
  • C# 的 xml 序列化中是否有一个属性可以跳过空数组?

    C 的 xml 序列化中是否有一个属性可以跳过空数组 这将提高 xml 输出的可读性 好吧 你也许可以添加一个ShouldSerializeFoo method using System using System ComponentMode
  • 自动将通配符导入重构为 IntelliJ 中的显式导入(适用于 Scala/Java)

    考虑下面的代码 是否可以让 IntelliJ 自动将每个通配符导入重构为显式导入 无论范围内使用什么 例如import scalatags JsDom all into import scalatags JsDom all ol li di
  • 返回右值 - 这段代码有什么问题? [复制]

    这个问题在这里已经有答案了 我遇到了以下代码片段 std string test std string m Hello return std move m int main std string m test 我知道上面的代码是不正确且不安
  • 使用 Powershell 或 C# 获取 Azure“文件和文件夹”作业状态

    我一直在尝试找到一种方法来获取在 AzureRM 中运行的几个客户上运行的 文件和文件夹 备份作业的状态 可以在 AzureRm 门户中手动找到状态 恢复服务保管库 gt 作业 gt 备份作业 使用powershell不显示任何作业信息 G
  • java 更新进度条

    我有一个 JFrame 和以下组件 JButton jButton1 Progress Bar ProgressBar 及其公共静态 JLabel 状态及其公共静态 单击按钮时会执行不同的语句 我想在每个语句后更新我的进度条 这是我的代码

随机推荐

  • id 重启event_系统已在未先正常关机的情况下重新启动 事件ID:41

    创建日期 2018 07 18 系统已在未先正常关机的情况下重新启动 事件ID 41 日志名称 System 来源 Microsoft Windows Kernel Power 日期 2018 7 17 23 55 06 事件 ID 41
  • do...while(0)的妙用

    在C 中 有三种类型的循环语句 for while 和do while 但是在一般应用中作循环时 我们可能用for和while要多一些 do while相对不受重视 但是 最近在读我们项目的代码时 却发现了do while的一些十分聪明的用
  • Km Kcat Kcat/Km

    max 是指 最大反应速度 当 底物浓度 足够大时 体系中 酶的活性中心达到饱和状态 其反应速度达到最大 由此可见 最大反应速度 max 随 酶浓度的变化而变化 kcat 指反应常数 catalytic constant kcat 可以由
  • python爬取小说(二)书籍基本信息爬取

    爬完数据目录和内容后 我们来爬取书籍的基本信息 在上篇博客的基础上 爬取书籍信息并存入字典 coding utf 8 import urllib request import bs4 import re import sqlite3 def
  • SpringBoot项目使用docker-maven-plugin插件构建docker镜像以及推送到docker hub或docker registry私服

    我们知道docker可将应用程序和基础设施层隔离 可更快地打包 测试以及部署应用程序 本文主要介绍SpringBoot项目如何构建docker镜像以及推送到私服或者docker hub服务器上 本文介绍的方式是使用docker maven
  • JAVA 反射机制--reflection

    1 关于JAVAf 反射机制的一些基本的介绍参见好搜百科http baike haosou com doc 5458411 5696799 html或者搜索关键字 JAVAf 反射机制 2 这里总结下JAVAf 反射机制是如何运用的 或者说
  • Python零基础小白快速上手,不多废话

    Python零基础小白快速上手 Markdown编辑器和python安装 Markdown编辑器就是程序员常用的记事本 https img blog csdnimg cn 20201031151738673 png pic center 这
  • ElementUI中的 el-table 怎样格式化显示1和0为男和女

    场景 数据库中存储的是int型的1和0 从数据中取出来的也是1和0 怎样将其格式化为男和女 实现 table 表格
  • java list转换类型_java List数据转换为json类型数据

    list new ArrayList for int i 0 i lt carouselImageList size i CarouselImage a carouselImageList get i if a null a new Car
  • grafana使用

    1 面板 1 1 添加面板 add a new panel 增加一个新的统计图 add a new row 多个panel集合在一起 例如overview 1 2 Panel 2 PromQL查询语句 2 1 计算每一个样本的占比 饼图展示
  • 使用RBF(径向基函数)网络进行Python编程

    使用RBF 径向基函数 网络进行Python编程 径向基函数 RBF 网络是一种常用的神经网络模型 它在许多领域中都有广泛的应用 如模式识别 函数逼近和时间序列预测等 本文将介绍如何使用Python编程实现RBF网络 并提供相应的源代码 首
  • 详细使用sqlite3教程及打包资源

    包含编译好的unicode 多字节两种静态库 和sqlite3 h 还有我自己写的详细使用sqlite3的类 完整可用 实际项目我用过 有不对的地方还请大家批评指正 https download csdn net download qq 3
  • 推荐一款 IDEA 生成代码神器,写代码再也不用加班了

    Easycode是idea的一个插件 可以直接对数据的表生成entity controller service dao mapper 无需任何编码 简单而强大 1 安装 EasyCode 我这里的话是已经那装好了 建议大家在安装一个插件 叫
  • 2021年华为OD面试总结

    文章目录 写在前面 面试总体流程 简历筛选 线上机考 综合评测 业务面试 背景调查和HR面试 主管面试 写在前面 笔者211重点大学本科 毕业近5年 因为之前不是学python的 是近两年入了编程教培行业 所以慢慢接触到的python 然后
  • 《数据结构与算法》实验:查找结构的实验比较——二叉查找树BST & 二分(折半)查找

    数据结构与算法 实验和课程Github资源 数据结构与算法 实验 线性结构及其应用 算术表达式求值 数据结构与算法 实验 树型结构的建立与遍历 数据结构与算法 实验 图结构的建立与搜索 数据结构与算法 实验 查找结构的实验比较 二叉查找树B
  • 优化学习01-尽量不在循环里进行查询

    背景 BI项目 查询导购的等级 前端访问调接口太慢了 排查了其他sql 发现是自己把查询放在循环里的原因 错误示范 修改方案 最终的结果 List
  • 汽车市场勇进派 乐车邦林金文的逆周期生意

    汽车后市场一度是资本方疯狂下注的互联网创业领域 但越疯狂就可能越惨淡 林金文是那种特别务实的创业者 这与他创业前在汽车行业里的成长经验密不可分 也是乐车邦能够经历资本寒冬与车市衰退而挺立潮头的缘故 作者 严 睿 编辑 刘 煜 潮水退去才知道
  • 实现Parcelable的bean中有数组对象

    package com whu travel whu bean import android os Parcel import android os Parcelable Created by Fly on 2016 8 2 public
  • 带你快速实现扇形图?

    首先我们需要了解一个新的概念 conic gradient 圆锥形渐变 特性 圆锥渐变的起始点是图形中心 渐变方向以顺时针方向绕中心旋转实现渐变效果 兼容性 根据 can i use 目前只在chrome 69及以上支持 可以使用polyf
  • 设计模式之工厂方法模式

    工厂方法模式 根据简单工厂模式的案例可知 如果我们想要添加一种立方运算 只需要创建一个立方运算类继承运算类 然后在工厂类中添加一个case分支用于逻辑判断 问题在于 我们在进行功能扩展的同时 也修改了工厂类中的代码 这很明显违背了开放 封闭