系统架构技能之设计模式-工厂模式

一、开篇

本文主要是讲述设计模式中最经典的创建型模式-工厂模式,本文将会从以下几点对工厂模式进行阐述。

image

本文将会从上面的四个方面进行详细的讲解和说明,当然会的朋友可以之处我的不足之处,不会的朋友也请我们能够相互学习讨论。

二、摘要

本文将会主要是结合项目中的一些实例作为实例来分析工程模式的使用方式和何时使用工程模式,并且分析工程模式的有点和它解决的问题,在我们实际的项目中何时能使用到它,或者

说我们在什么情况下,应该考虑使用工厂模式来解决项目中的问题,一般情况下我们可以这样理解设计模式,设计模式是一种方案,为我们遇到与设计模式提出的应用场景想象或者相仿的场景

中,这类问题通常是经常发生或者是经常遇到的问题的通用解决方案。

本文依然是采用图文讲解的形式来分析工程模式在项目中出现的位置,并且给出几个灵活的实现方案。主要针对的实现方式有:通过配置文件,通过类型,通过委托,通过特性等来实现工厂。

三、本文大纲

a、开篇。

b、摘要。

c、本文大纲。

d、工厂模式的特点及使用场景。

e、工厂模式的实现方案。

f、工厂模式使用总结。

g、系列进度。

h、下篇预告。

四、工厂模式的特点及使用场景

4.1、工厂模式简介

工厂模式是创建型模式中最典型的模式,主要是用来创建对象,减少我们在使用某个对象时的new() 操作,我相信大家都有这样的困惑,目前我所在的项目都在程序开发的过程中,还是

有很多的new()操作出现在表现层中,并没有通过工厂来创建对象,一方面可能是因为我们自身比较懒,不规范项目的编码形式,另外一方面也是由于项目的进度比较紧,没有那么多的时间去

完成工厂的统一创建,当然对于这样的动态创建对象的工厂,推荐的做法还是我们后面会讲到的创建型模式–《抽象工厂模式》来解决吧。

如果您并不知道工厂模式是用来干什么的,我们可以通过如下举例来说明,例如我们现在有个矿泉水加工厂,加工矿泉水,我们现在知道有矿泉水这个对象,那么当我批量生产矿泉水的

时候,我们就通过工厂来批量的生产,等于我们程序中的批量创建对象。这时候我有很多个对象,也就是很多游客,他们每人都要一瓶矿泉水,这时候如果说把游客比作不同的应用程序模块,

都要使用矿泉水这个对象,那么我是不是应该每个应用程序都在使用这个对象的时候,我使用new()操作呢?,无疑这不是一个好的方案。我们来看看图形化的描述吧?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传这种情况下,不同的游客需要矿泉水的时候,我就new()一个矿泉水和我找个加工厂生产矿泉水明显是有差别的,这个时候,游客不应该和矿泉水有

关联关系了,而且游客不知道,矿泉水是怎么生产出来的,也不需要关心这些东西。

那么我们应该如何去解决这样的问题呢?基于面向对象的变成设计时,原则就是低耦合,对象和对象之间。那么对象之间的引用关系,可以通过抽象出接口,通过借口的依赖来解耦,降低系统的耦合性。

image假如这个时候我修改对象服务的名称,那么我是不是必须把所有的调用这个对象服务应用程序代码都进行

修改?这个是必须的,否则程序无法编译通过的。但是如果我们使用工厂模式的时候呢?有什么不同呢?我们来看看:

image上面是添加了工厂模式之后的情况,上面就算是你修改了类名之后,只

需要修改工厂中的New出来的类即可,当然如果你要是通过返回接口的形式的话,再不修改接口命名的前提下,如何修改类方法都是可行的,并且通过工厂模式,无疑降低了应用程序与对象之

间的耦合性,通过工厂来解耦,提供程序的应对变化的适应能力。

4.2、工厂模式的使用场景

工厂模式一般用于创建一类对象,而不用每次在使用时通过new()对象才能使用对象,而是通过工厂来完成对象的创建,这样不但提供了统一创建对象的入口,而且对于程序的可维护

和可测试性都有很大的提高。总体来说如下场景使用工厂模式非常合适:

1、工厂负责创建某一类对象的时候,或者说工厂的职责比较单一时,如果说多个类型的对象时候,用工厂模式就不如使用抽象工厂了

2、一般比较少的积累对象,可以通过类型的判定创建不同的对象时,也是可以通过工厂模式来完成,例如多数据库的支持,我们在设计数据访问层时,利用简单对象工厂,通过枚举或

者配置文件的形式,来动态的创建数据访问层实例。

3、一般来说类型单一的对象,或者类型比较少的时候,使用工厂模式来创建对象可以解决一类问题。还可以通过一个总的工厂,来创建多个工厂,然后多个工厂负责创建相应的实例,

有点类似我们平时说的目录结构似的。

类似如下的形式,大家一看就明白了:

image

等于是不同层级的工厂,具有不同的职责和任务。

五、工厂模式的实现方案

5.1、工厂模式的配置文件实现。

我们先看配置文件的配置内容

default MSSQLServer

定义要创建的对象实例统一接口

///
/// 所有的数据访问接口
///
public interface IDbAccess
{
}

实现这个接口的具体类

public class SQLServer : IDbAccess
{
//相关的方法
public System.Data.SqlClient.SqlConnection Connection
{
get
{
return new System.Data.SqlClient.SqlConnection();
}
}
}

负责创建返回类型为IDbAccess的数据访问层对象实例

public class DBFactory
{
public IDbAccess Create()
{
IDbAccess instance = null;

System.Xml.XmlDocument doc=new System.Xml.XmlDocument();
doc.LoadXml(“”);

XmlElement root = doc.DocumentElement;//XML文档的根节点
XmlNode node = root.SelectSingleNode(“DataBaseType”);

switch (node.InnerText)
{
case “SQLServer”:
instance = new SQLServer();
break;
case “Oracle”:
instance = new Oracle();
break;
default:
break;
}

return instance;
}
}

具体的控制台输出测试代码如下:

class Program
{
static void Main(string[] args)
{
DBFactory factory = new DBFactory();
IDbAccess dbaccess = factory.Create();

//使用相应的数据访问对象即可。
}
}

5.2、通过枚举来实现。

通过枚举来实现后,工厂类的创建代码如下:

public class DBFactory
{
public IDbAccess CreateByEnum(DbType dbType)
{
IDbAccess dbAccess = null;

switch ((int)dbType)
{
case (int)DbType.SQLServer:
dbAccess= new SQLServer();
break;
case (int)DbType.Oracle:
dbAccess = new Oracle();
break;
case (int)DbType.Access:
dbAccess = new Access();
break;
default:
break;
}

return dbAccess;
}
}

相应的枚举代码如下:

public enum DbType
{
SQLServer=0,
Oracle=1,
Access=2
}

相应的控制台测试代码:

static void Main(string[] args)
{
DBFactory factory = new DBFactory();
IDbAccess dbaccess = factory.CreateByEnum(DbType.SQLServer);

//使用相应的数据访问对象即可。
}

5.3、工厂模式的复杂进阶

我们上面只是定义了一种工厂,该工厂负责所有的子类对象的创建,如果说我们的工厂要求能够满足增加新的对象时,我们必须修改工厂代码,那么我们如何来做呢?我们可以这

样来做。

image每个类型的对象都有与这个类型对应的工厂去创建,那么就算以后增加或者修

改,只需要修改相应的工厂涉及的文件即可。但是这样也有很大的弊端就是工厂类太多,难以维护。优点是支持动态的增加新的对象类型,对之前的创建工作不会造成影响,我们

来看看相应的代码,基于图中的几个类型。先定义对象的统一接口和工厂的接口。

先看对象接口的统一定义:

public interface IComObject
{
///
/// 重要级别
///
///
int ImportLevel();
}

工厂接口的统一定义:

public interface IComFactory
{
IComObject Create();
}

我们来看看具体的对象实现和工厂实现吧,我们这里以上图中的书为例说明创建过程

public class BookFactory : IComFactory
{
public IComObject Create()
{
return new Book();
}
}

具体的对象实现代码-实现IComObject对象接口

public class Book : IComObject
{
public int ImportLevel()
{
return 0;
}
}

我们来看看具体的程序调用代码:

static void Main(string[] args)
{
IComFactory factory = new BookFactory();
IComObject book = factory.Create();

//使用相应的数据访问对象即可。
}

通过上面的形式,我们可以看到,后期如果新增比如说我现在要对个产品这个对象新增到系统中,那么我们只需要增加相应的对象实现类和工厂实现类即可,对其他地方不会有影

响,相比上面讲述的,一个工厂创建所有的对象实例的方式无疑提供了新增对象类型创建的能力。

六、工厂模式使用总结

通过上面的简单实例讲解,估计高手理解起来很容易也很简单,其实本来也是很简单的,大伙不了解工厂模式的朋友,应该也能理解讲述的内容,本文前面讲述的2中方式主要是针对简

单工厂模式,简单工厂模式,不符合高内聚的原则,因为所有的对象的创建工作都放在一个类的内部去完成,逻辑太复杂了,通过后面的工厂模式,将每个工厂的职责进行了更细化,每个工厂

只负责具体对象类型实例的创建。这也为后期增加新的对象类型提供了不错的扩展,本文并没有给出特性+委托的工厂的实现方案,我放在下篇的抽象工厂中去讲解,也会针对配置文件,特性,委

托的几种方式来给出抽象工厂模式的实现方案,当然我给出的都是很简单的例子,希望大家一看就懂,就能用在实际的项目中,可能高手会认为我讲的太浅了,一方面是因为自己没有整理好思

路,时间紧迫,另一方面是因为自身能力有限,还请大家多提宝贵意见,我们总结下本文讲述的内容吧;

前面讲述了2中简单工厂模式的实现方案。通过配置文件、通过枚举来完成对象的创建,其实就是根据对象的类型来完成,也可以通过反射来完成。这里给出简单的实现:

public IDbAccess Create(string TypeName)
{
Type type = Type.GetType(TypeName);
IDbAccess obj = (IDbAccess)Activator.CreateInstance(type);
return obj;
}

其实就是这样的简短代码,给出关键代码实现吧,可能实际运行中还要进行相应的调整。

总体来说简单工厂适合项目中类型不多的情况时使用简单工厂很方便。

当项目中频繁的增加不同类型的对象时,考虑使用工厂模式,来满足这样的动态变化需求。

七、系列进度

创建型

1、系统架构技能之设计模式-单件模式

2、系统架构技能之设计模式-工厂模式

3、系统架构技能之设计模式-抽象工厂模式

4、系统架构技能之设计模式-创建者模式

5、系统架构技能之设计模式-原型模式

结构型

1、系统架构技能之设计模式-组合模式

2、系统架构技能之设计模式-外观模式

3、系统架构技能之设计模式-适配器模式

4、系统架构技能之设计模式-桥模式

5、系统架构技能之设计模式-装饰模式

6、系统架构技能之设计模式-享元模式

7、系统架构技能之设计模式-代理模式

行为型

1、系统架构技能之设计模式-命令模式

2、系统架构技能之设计模式-观察者模式

3、系统架构技能之设计模式-策略模式

4、系统架构技能之设计模式-职责模式

5、系统架构技能之设计模式-模板模式

6、系统架构技能之设计模式-中介者模式

7、系统架构技能之设计模式-解释器模式

八、下篇预告。

下篇将会针对抽象工厂模式进行讲述,该模式也是目前项目中使用最多的一个设计模式,目前我所在的项目中,就使用到了这个模式,我会对于前面讲述的工厂模式与抽象工厂模式进行对比,并且把今天文章中提到的特性+委托的方案放出实现,希望大家多提宝贵已经,错误之处还请指出,请大家继续支持。

九、本文源码

下载源码
转自:https://www.cnblogs.com/hegezhou_hot/archive/2010/11/30/1892227.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java后端开发面试题——企业场景篇

单点登录这块怎么实现的 单点登录的英文名叫做:Single Sign On(简称SSO),只需要登录一次,就可以访问所有信任的应用系统 JWT解决单点登录 用户访问其他系统,会在网关判断token是否有效 如果token无效则会返回401&am…

C#循环定时上传数据,失败重传解决方案,数据库标识

有些时候我们需要定时的上传一些数据库的数据,在数据不完整的情况下可能上传失败,上传失败后我们需要定时在重新上传失败的数据,该怎么合理的制定解决方案呢?下面一起看一下: 当然本篇文章只是提供一个思路&#xff0…

SAP-PP:基础概念笔记-5(物料主数据的MRP1~4视图)

文章目录 前言一、MRP1视图Base Unit of Measure(UoM)MRP 组采购组ABC 指示器Plant-Specific Material Status 特定的工厂物料状态MRP 类型 MRP TypeMRP 类型 MRP TypeMaster Production Scheduling(MPS) 主生产计划基于消耗的计划(CBP)再订货点Reorder-…

uni-app点击复制指定内容(点击复制)

官方api uni.setClipboardData(OBJECT) uni.setClipboardData({data: 要被复制的内容,success: function () {console.log(success);} });

Liquid UI和Fiori的区别

主要围绕以下几个方面就Liquid UI和Firor来进行比较: 开发周期开发成本稳定性和支援性平台架构 影响Firor决策的因素: 复杂的编程过程,Fiori对开发人员要求高,开发难度大,而Liquid UI让开发人员不需要懂SAP后端&…

yolov5运行过程遇到的小问题(随时更新)

1.关于git的问题 解决办法:插入下面代码 import os os.environ["GIT_PYTHON_REFRESH"] "quiet"2.页面太小无法完成操作 解决办法: 如果不好使再考虑降低Batch_Size大小或者调整虚拟内存可用硬盘空间大小!(调整虚拟内存…

整理mongodb文档:分页

个人博客 整理mongodb文档:分页 个人博客,求关注,如果文章不够清晰,麻烦指出。 文章概叙 本文主要讲下在聚合以及crud的find方法中如何使用limit还有skip进行排序。 分页的情况很经常出现,这也是这篇博客诞生的理由。 数据准备…

Vue组件之间传值

聊一聊vue里面组件之间的传值 首先总结一下vue里面传值的几种关系: 如上图所示, A与B、A与C、B与D、C与F组件之间是父子关系; B与C之间是兄弟关系;A与D、A与E之间是隔代关系; D与F是堂兄关系,针对以上关系 我们把组件…

Redis 缓存穿透击穿和雪崩

一、说明 Redis 缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对…

Nginx基础+高级(2022版):待更新

1. 文章说明 说明:目前讲的是第一部分nginx核心技术篇,后需篇章会以第一部分为核心技术篇为基础来展开深度讲解,详情关注后续课程的发布。 2. 介绍和准备环境 2.1 介绍 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xf…

动态维护直径 || 动态维护树上路径 || 涉及LCA点转序列 || 对欧拉环游序用数据结构维护:1192B

https://www.luogu.com.cn/problem/CF1192B 对于直径的求法,常用dp或两次dfs,但如果要动态维护似乎都不太方面,那么可以维护树上路径最大值。 树上路径为: d e p u d e p v − 2 d e p l c a ( u , v ) dep_udep_v-2\times de…

iPhone 15 Pro展示设计:7项全新变化呈现

我们不应该再等iPhone 15 Pro在苹果9月12日的“Wonderlust”活动上发布了,而且可能会有很多升级。有传言称,iPhone 15 Pro将是自iPhone X以来最大的飞跃,这要归功于大量的新变化,从带有更薄边框的新钛框架到顶级A17仿生芯片和动作…

[管理与领导-70]:IT基层管理者 - 辅助技能 - 4- 职业发展规划 - 个人的能力盘点

目录 前言: 一、什么是能力(What) 1.1 什么是能力 1.2 能力类型 1.3 技能矩阵 二、优势与劣势模型 2.1 优势与劣势 2.2 SWOT模型 三、人才结构模型 3.1 广度优先:一字型/全面型人才 3.2 深度优先:I型人才、…

Django框架中使用drf框架开发

一、drf框架特点: 全称 Django REST framework 两大部分:序列化/反序列化 和 增删改查序列化:把数据库数据提取出来变成python常用格式的过程,例如转成json格式这种反序列化:把数据写入到数据库的过程&#xff0c…

浅谈一下酒吧和酒馆的不同

相信有很多朋友还不怎么清楚酒吧和酒馆的区别是什么,这里为大家简单介绍一下两者的不同,个人见解,如有错漏,欢迎指出。一、首先是他们的经营范围不同酒馆经营通常包含酒水和餐饮,适合朋友聚会或者是和商业伙伴聊天。而…

QLoRA:量化LLM的高效微调策略与实践

如果你对这篇文章感兴趣,而且你想要了解更多关于AI领域的实战技巧,可以关注「技术狂潮AI」公众号。在这里,你可以看到最新最热的AIGC领域的干货文章和案例实战教程。 一、前言 在大型语言模型(LLM)领域,微…

(位运算) 剑指 Offer 15. 二进制中1的个数 ——【Leetcode每日一题】

❓ 剑指 Offer 15. 二进制中1的个数 难度:简单 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为 汉明重量).)。 提示&#xff…

计算机网络自顶向下-web页面请求历程

1. 准备: DHCP、 UDP、 IP 和以太网 假定 Bob 启动他的便携机,然后将其用一根以太网电缆连接到学校的以太网交换机 , 交换机与学校的路由器相连。学校的路由器与一个 ISP 连接, 本例中 ISP 为 comcast.net ,为学校提供了 DNS 服务…

开发前期准备工作

开发前期准备工作 文章目录 开发前期准备工作0 代码规范0.1 强制0.2 推荐0.3 参考dao:跟数据库打交道service:业务层,人类思维解决controller:抽象化 0.4 注释规范0.5 日志规范0.6 专有名词0.7 控制层统一异常统一结构体控制层提示…

java线程和go协程

一、线程的实现 线程的实现方式主要有三种:内核线程实现、用户线程实现、用户线程加轻量级进程混合实现。因为自己只对java的线程比较熟悉一点,所以主要针对java线程和go的协程之间进行一个对比。 线程模型主要有三种:1、内核级别线程&#…