【设计模式】什么场景可以考虑使用简单工厂模式

1.概述

工厂模式是一种创建型模式,主要作用就是创建对象,将对象的创建过程和使用的过程进行解耦。我们平时说的工厂模式实际上是对三种不同类型的工厂模式的统称,简单工厂、工厂方法、抽象工厂,而在23种设计模式中,只定义了工厂方法和抽象工厂,将简单工厂看作是工厂方法的一种特例,本篇主要讲述的是简单工厂

简单工厂,就像它的名字一样突出一个简单,就是将业务流程代码中直接使用new关键字来创建对象,修改为通过一个工厂类创建对象,这就是简单工厂。如果仅仅只是将new操作转移到了一个新的类里面,看起来只是在徒增类的数量和代码量,并没有什么意义。

那为什么我们还要使用简单工厂模式呢?
是因为它在某些特定的场景下有其存在的价值,让我们从不同的场景来看看。

2.从不同场景看简单工厂的意义

2.1.框架或工具的封装

除了日常业务开发之外,有时候我们也可能得做一些框架或者工具的开发,这部分开发出来的工具需要提供给其他的开发人员使用,而他们在使用的时候,第一步就是获取到这个工具的对象,这种情况下就可以给使用者提供一个简单工厂,让使用者通过工厂来创建对象。
例如在Java中使用日历相关的工具Calendar就是通过简单工厂提供的获取日历对象的方法,如下图:
在这里插入图片描述
我们做类似的框架或工具开发的时候,完全可以参照Calendar的方式,给使用者提供创建对象的能力,从而让使用者无需关心对象的实际创建过程,而是只需要通过特定的方法和参数,就能获取到一个可供使用的对象。

2.2.复杂业务对象的创建

即使是在做业务相关开发,有时候也会涉及到一些相对复杂的业务对象的创建(例如DDD中的领域对象),这时候可以使用简单工厂将产品对象的创建流程从业务流程中抽离。由于创建对象的复杂性被隔离在工厂类中,因此当涉及到产品类的变化时,比如增加新功能、改变实现方式等,只需要改动工厂类,不会对使用产品的其他模块造成影响,有利于产品创建逻辑的集中管理,以及系统的维护和版本升级。


之前在做一个项目开发的时候使用过简单工厂处理过Domain对象的创建,先说一下背景:

这个项目使用的时COLA架构(一种DDD的代码层面实践的框架),在这个架构的分层中Domain层属于最底层,如下图中的demoWeb-domain
在这里插入图片描述
Domain层中会完成大部分的业务逻辑,但我们知道业务流程中往往伴随着与中间件其他服务之间的交互(例如数据库的存取操作),但这部分交互不应该由领域对象来实现。

COLA中的做法就是提供一个“防腐层”来实现,所谓的防腐层就是在domain层中定义与中间件交互的interface再交由infrastructure来实现,这样在domain层就只需要关心自己需要做一个什么交互,而不需要关心具体的交互实现,如下的红框所示。
在这里插入图片描述
背景介绍完了,说一下这里面存在一个问题,就是Domain对象为了保证业务模型的纯洁性,一般不会使用Spring来管理领域对象的生命周期,在这种情况下如何才能将gatewayImpl对象注入到领域对象中呢?

答案是在Infrastructure层中,将getewayImpl对象set到领取对象中,如果领域对象的创建过程相对复杂,就可以使用简单工厂进行创建,统一管理创建逻辑,代码如下:

@Component
public class MsgWecomAppFactory {

    @Resource
    private MsgWecomGateway msgWecomGateway;
    @Resource
    private MsgWecomCacheGateway msgWecomCacheGateway;

    @Resource
    private WecomHttpHelper wecomHttpHelper;

    /**
     * 创建企业微信应用号领域对象,用于确认消息
     *
     * @param agentId 应用号ID
     * @return 领域对象
     */
    public MsgWecomApp createMsgWecomAppForConfirm(String agentId) {
        MsgWecomApp msgWecomApp = new MsgWecomApp();
        // 1.查询企业微信应用配置信息
        Optional<MsgWecomAppConfig> appConfig = msgWecomGateway.getWecomAppConfigByAgentId(agentId);
        Assert.isTrue(appConfig.isPresent(), "企业微信应用号配置信息不存在,执行失败,agentId:" + agentId);
        msgWecomApp.setConfig(appConfig.get());

        msgWecomApp.setMsgWecomCacheGateway(msgWecomCacheGateway);
        msgWecomApp.setMsgWecomGateway(msgWecomGateway);
        msgWecomApp.setWecomHttpHelper(wecomHttpHelper);
        return msgWecomApp;
    }

    /**
     * 创建企业微信应用号领域对象,用于发送消息
     *
     * @param agentId 应用号ID
     * @param phones  手机号
     * @return 领域对象
     */
    public MsgWecomApp createMsgWecomAppForSend(String agentId, Set<String> phones) {
        MsgWecomApp msgWecomApp = new MsgWecomApp();
        // 1.查询企业微信应用配置信息
        Optional<MsgWecomAppConfig> appConfig = msgWecomGateway.getWecomAppConfigByAgentId(agentId);
        Assert.isTrue(appConfig.isPresent(), "企业微信应用号配置信息不存在");
        msgWecomApp.setConfig(appConfig.get());

        // 2.查询用户信息,优先使用手机号查询,如果手机号为空或手机号未查询到则使用邮箱查询
        List<MsgWecomMemberInfo> msgWecomMemberInfos = new ArrayList<>();
        if (CollUtil.isNotEmpty(phones)) {
            msgWecomMemberInfos = msgWecomGateway.listWecomMemberInfoByPhone(phones);
            // 对比参数中的手机号与查询到的手机号,获取差集
            List<String> existPhone = msgWecomMemberInfos.stream().map(MsgWecomMemberInfo::getPhone).collect(Collectors.toList());
            msgWecomApp.setNotExistPhones(CollUtil.subtractToList(phones, existPhone));
        }

        msgWecomApp.setToSendMemberInfos(msgWecomMemberInfos);

        msgWecomApp.setMsgWecomCacheGateway(msgWecomCacheGateway);
        msgWecomApp.setMsgWecomGateway(msgWecomGateway);
        msgWecomApp.setWecomHttpHelper(wecomHttpHelper);
        return msgWecomApp;
    }
}

2.3.与其他模式的组合使用

策略模式中的选择器实现:
在SpringBoot优雅使用策略模式这一篇博客中提到了如何使用Spring对Bean的管理能力,来实现策略模式的选择器。同样的,如果没有使用Spring或者业务对象的生命周期不需要Spring框架介入时,就可以使用简单工厂+单例的方式来实现,代码如下:

/**
 * 策略选择器工厂
 */
public class StrategySelectorFactory {

    private static final Map<String, Strategy> STRATEGY_MAP = new java.util.HashMap<>();

    static {
        STRATEGY_MAP.put("A", new StrategyA());
        STRATEGY_MAP.put("B", new StrategyB());
    }

    public static Strategy getStrategy(String strategyKey) {
        if (strategyKey == null || strategyKey.isEmpty()) {
            throw new IllegalArgumentException("strategyKey can not be empty");
        }
        return STRATEGY_MAP.get(strategyKey);
    }
}

3.总结

本篇主要讲述了工厂模式中的特例:简单工厂模式,并通过3种不同的场景来介绍这种模式存在的意义,有以下几方面:

  • 封装对象创建过程: 将对象的创建过程封装工厂类中,使用者无需了解具体产品的创建细节,只需调用工厂类提供的静态方法即可得到所需的产品对象。这样可以隐藏产品类的具体实现,降低耦合度。
  • 控制逻辑集中: 将复杂对象的创建对象逻辑集中在工厂类中,如果需要修改或扩展产品类型时,只需要修改工厂类中的代码。这使得添加新产品或者调整产品创建逻辑更加方便、集中管理,也有利于系统的维护和版本升级
  • 组合其他模式满足特定的需求: 在某些应用场景中,如根据参数动态选择不同类型的对象实例化,简单工厂+单例提供简洁有效的解决方案,避免了直接使用 new 关键字创建对象带来的硬编码问题。

最后,虽然简单工厂模式在一定程度上提高了灵活性和可维护性,但它也有其局限性,例如违反了开闭原则,每增加一个新产品就需要修改工厂类的代码。

但瑕不掩瑜,简单工厂模式在很多简单场景下发挥着重要的作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/320758.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VSCode编写 C/C++ 程序

VSCode 全称 Visual Studio Code&#xff0c;是微软出的一款轻量级代码编辑器&#xff0c;免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性&#xff0c;支持插件扩展&#xff0c;并…

SG-8101CGA 系列 (晶体振荡器 可编程 可用 +125°C )

SG-8101CGA是可编程晶体振荡器&#xff0c;具有CMOS输出&#xff0c;适用于汽车&#xff0c;同时&#xff0c;该系列还提供相同的频率和其他参数的轻松编程能力&#xff0c;符合AEC-Q100标准&#xff0c;具有出色的电磁兼容性和稳定性&#xff0c;可以在各种环境下使用。外部尺…

Linux下编写zlg7290驱动(1)

大家好&#xff0c;今天给大家介绍Linux下编写zlg7290驱动(1)&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 在智能仪表中&#xff0c;经常会用到键盘、数码管等外设。因此&…

Windows Server 2012 R2部署项目

JDK 下载JDK 1.直接官网下载&#xff1a;http://www.oracle.com/&#xff1b; 2.我用的是1.8&#xff0c;阿里云盘分享地址&#xff1a;https://www.aliyundrive.com/s/u4V9x1AHL2r 安装jdk 双击安装点击下一步如果不改变路径就一直下一步 安装完成直接点击关闭即可&#x…

高光谱分类论文解读分享之基于形态卷积神经网络的高光谱影像分类

IEEE TGRS 2021&#xff1a;基于形态卷积神经网络的高光谱影像分类 题目 Morphological Convolutional Neural Networks for Hyperspectral Image Classification 作者 Swalpa Kumar Roy; Ranjan Mondal; Mercedes E. Paoletti; Juan M. Haut; Antonio Plaza 关键词 Clas…

鸿蒙开发基础-Web组件之cookie操作

使用ArkTS语言实现一个简单的免登录过程&#xff0c;向大家介绍基本的cookie管理操作。主要包含以下功能&#xff1a; 获取指定url对应的cookie的值。设置cookie。清除所有cookie。免登录访问账户中心。 cookie读写操作 首次打开应用时&#xff0c;应用首页的Web组件内呈现的…

【OJ】环形链表

目录 1. 环形链表||&#xff08;142&#xff09;1.1 题目描述1.2 题目分析1.3 代码 2. 环形链表&#xff08;141&#xff09;2.1 题目描述2.2 题目分析2.3 代码 1. 环形链表||&#xff08;142&#xff09; 1.1 题目描述 1.2 题目分析 带环链表&#xff1a;尾节点的next指向链…

Windows之任意文件删除到提权

前言 ZDI 发表过从任意文件夹删除到提权的利用过程&#xff0c;还提供了任意文件删除到提权的利用过程&#xff0c;所以一字之差但是漏洞利用方式也是有细微偏差的。 这里把任意文件删除和任意文件夹删除漏洞提权结合起来分析&#xff0c;是因为其最后的利用过程是一样的&…

第二节课 书生·浦语大模型趣味 Demo笔记及作业

文章目录 笔记作业基础作业&#xff1a;进阶作业&#xff1a; 笔记 书生浦语大模型InternLM-Chat-7B 智能对话 Demo&#xff1a;https://blog.csdn.net/m0_49289284/article/details/135412067书生浦语大模型Lagent 智能体工具调用 Demo&#xff1a;https://blog.csdn.net/m0_…

k8s node节点加入集群,token过期

1、master01节点执行 kubeadm token create --print-join-command 2、执行命令 kubeadm join 192.168.0.236:16443 --token qucd8q.hsfq4a1afluzaky3 --discovery-token-ca-cert-hash sha256:92175a356db070deb2ddd3823e288e3005a4baeec9b68580dcc11ce4d3767195 3、查看node02…

C++学习笔记——SLT六大组件及头文件

目录 一、C中STL&#xff08;Standard Template Library&#xff09; 二、 Gun源代码开发精神 三、 实现版本 四、GNU C库的头文件分布 bits目录 ext目录 backward目录 iostream目录 stdexcept目录 string目录 上一篇文章&#xff1a; C标准模板库&#xff08;STL&am…

光猫(无限路由器)插入可移动硬盘搭建简易版的NAS

1.场景分析 最近查询到了许多有关NAS的资料&#xff0c;用来替代百度云盘等确实有很多优势&#xff0c;尤其是具有不限速&#xff08;速度看自己配置&#xff09;、私密性好、一次投入后续只需要电费即可等优势。鉴于手上没有可以用的资源-cpu、机箱、内存等&#xff0c;查询到…

ISO11898-闭环高速CAN网络 (125K~1Mbps)

ISO11898 标准的物理框图如下图 可理解为一个高速闭环 CAN 总线网络&#xff1b;CAN 闭环总线网络允许总线最大长度为 40m;最高速度为 1Mbps;可以看到总线的两端各有一个 120Ω 的电阻&#xff0c;此电阻作为阻抗匹配功能&#xff0c;以减少回波反射;节点就是不同的设备&#…

Embeddings: What they are and why they matter

embeddings 是什么意思https://simonwillison.net/2023/Oct/23/embeddings/推荐原因&#xff1a;GPT 模型的基础是一种叫做 embeddings 的技术&#xff0c;用来将文本转换成向量&#xff0c;从而可以计算出文本之间的相似度。这篇文章详细地介绍了embeddings及应用 Embeddings…

HTML--CSS--边框、列表、表格样式

边框样式 属性&#xff1a; border-width 边框宽度 border-style 边框外观 border-color 边框颜色 需要同时设定三个属性 border-width 边框宽度 取值为像素值 border-style 边框样式 none 无样式 dashed 虚线 solid 实线 border-color 边框颜色 如示例&#xff1a; 为div设…

NLP论文阅读记录 - 2021 | WOS 使用深度强化学习及其他技术进行自动文本摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1. Seq2seq 模型2.2.强化学习和序列生成2.3.自动文本摘要 三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 Auto…

Python Matplotlib 动画教程:提高可视化吸引力的强大工具【第24篇—python:Matplotlib】

文章目录 &#x1f356; 方法一&#xff1a;使用pause()函数&#x1f680; 方法二&#xff1a;使用FuncAnimation()函数&#x1f94b; 线性图动画&#xff1a;&#x1f3bb; Python中的条形图追赶动画&#x1f30c; Python中的散点图动画&#xff1a;&#x1f6f9; 条形图追赶的…

<软考高项备考>《论文专题 - 65 质量管理(4) 》

4 过程3-管理质量 4.1 问题 4W1H过程做什么为了评估绩效&#xff0c;确保项目输出完整、正确且满足客户期望&#xff0c;而监督和记录质量管理活动执行结果的过程作用&#xff1a;①核实项目可交付成果和工作已经达到主要干系人的质量要求&#xff0c;可供最终验收;②确定项目…

乐意购项目前端开发 #2

一、Axios的安装和简单封装 安装Axios npm install axios在utils目录下创建 http.js 文件, 内容如下 import axios from axios// 创建axios实例 const http axios.create({baseURL: http://localhost:9999,//后端服务器地址timeout: 5000 })// axios请求拦截器 http.interc…
最新文章