C# 创建型设计模式----工厂模式
1 、什么是工厂模式
简单来说就是由一个对象去生成不同的对象,工厂模式是用工厂方法代替new操作的一种模式。工厂方法封装了多个相关联类的new方法,每次实例化这些类的时候不需要new多次,只需要调用工厂类的对应方法即可实例化这些类,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式主要有三种类型:简单工厂(不介绍)、工厂方法和抽象工厂。
2、工厂模式的作用
在创建对象时必然需要new该对象,当需要更改对象时,需要把项目中所有地方都修改一遍,这显然违背了软件设计的开闭原则。如果使用工厂来生成对象,那么我们只需要跟工厂打交道就可以了。如果要更新对象时,直接在工厂里更换即可。这就实现了对象解耦。
所以工厂模式主要用来解耦代码,将对象的创建和使用分离,使得代码更加灵活和可维护。
3、工厂方法
3.1、工厂方法模式的主要角色:
抽象工厂:在抽象工厂类中声明了工厂方法,用于返回一个产品。提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
具体工厂:它是抽象工厂类的子类,实现了在抽象工厂中声明的工厂方法,完成具体产品的创建。并可由客户端调用,返回一个具体产品类的实例。
抽象产品:它是定义产品的接口,定义了产品的规范,描述了产品的主要特性和功能,是工厂方法模式所创建对象的公共父类。
具体产品:它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间相互对应。
3.2、创建工厂方法
抽象工厂:提供基类,通俗理解就是。有这么一个专门生产电蒸锅的集团架构(别问为什么是电蒸锅,因为我现在想买)。集团不提供锅,只提供流水线的基建,和产品的基本概念。
/// <summary>///抽象工厂--电蒸锅集团,专门生产各种电蒸锅/// </summary>public abstract class ElectricFactory{/// <summary>/// 声明获取抽象产品类方法(具体实现在其子类)--提供生产电蒸锅的流水线,流水线具体怎么生产,生产哪种集团不管/// </summary>/// <returns></returns>public abstract Electric GetElectric();}
具体工厂:继承抽象工厂--也就是具体的生产厂家,都是继承集团的流水线并定义里面具体的生产方式
/// <summary>
/// 具体工厂-美的流水线
/// </summary>
public class MDElectricFactory : ElectricFactory//美的属于该集团下的工厂
{/// <summary>/// 实现抽象方法,具体操作在里面/// </summary>/// <returns></returns>public override Electric GetElectric()//美的使用集团提供的流水线,集团提供什么,美的就能使用什么{Console.WriteLine("美的生产了一个锅");return new MDElectric();//返回具体产品-美的电蒸锅}
}
/// <summary>
/// 具体工厂-苏泊尔流水线
/// </summary>
public class SBRElectricFactory : ElectricFactory//苏泊尔属于该集团下的工厂
{/// <summary>/// 实现抽象方法,具体操作在里面/// </summary>/// <returns></returns>public override Electric GetElectric()//使用集团提供的流水线{Console.WriteLine("苏泊尔生产了一个锅");return new SBRElectric();//返回具体产品-苏泊尔电蒸锅}
}
抽象产品:集团告诉你这是电蒸锅,它有什么功能,下面的工厂生产的产品得有这个功能,至于功能怎么实现的集团不管。
/// <summary>
/// 抽象产品电蒸锅---集团定义的电蒸锅整个品类
/// </summary>
public abstract class Electric
{/// <summary>/// 抽象方法-定义电蒸锅有蒸东西的基本功能,具体怎么蒸就是下面的厂家决定。/// </summary>public abstract void Fun();/// <summary>/// 抽象产品提供拓展方法--子类产品非必须使用的,但可以有,就像有些电蒸锅有预约功能,有些没有。/// 而且最好是具体产品的共有的特性(公共方法),不建议是小众特性(仅适用于某个具体产品的方法),/// 例如电蒸锅的预约功能就很大众,可以有,/// 如果某个厂家要加一个烤盘功能,这就属于小众,放在具体厂家那里去实现更合适。/// </summary>public void AddFunction(string name){Console.WriteLine($"{name}加了一个预约功能");}
}
具体产品:电蒸锅的蒸东西的功能具体实现方式
/// <summary>/// 具体产品-美的电蒸锅/// </summary>public class MDElectric : Electric//这是美的电蒸锅,必须包含集团定义的电蒸锅的必备功能的同时也可以自己拓展{/// <summary>/// 具体的实现方法/// </summary>public override void Fun(){Console.WriteLine("美的电蒸锅蒸东西的功能是用大火蒸东西");}}/// <summary>/// 具体产品-苏泊尔电蒸锅/// </summary>public class SBRElectric : Electric//这是苏泊尔电蒸锅{public override void Fun(){Console.WriteLine("苏泊尔电蒸锅蒸东西的功能是用中火蒸东西");}}
使用:
private void WTBtn_Click(object sender, EventArgs e)
{ElectricFactory electric;//创建了一个电蒸锅集团。electric = new MDElectricFactory();//美的接入集团var DZG = electric.GetElectric();//美的使用集团生产线,定义生产线的具体流程并生产一个锅DZG.Fun();//这个锅实现具体的功能electric = new SBRElectricFactory();//苏泊尔接入集团var DZG1 = electric.GetElectric();//苏泊尔使用集团生产线,定义生产线的具体流程并生产一个锅DZG1.Fun();//这个锅实现具体的功能DZG1.AddFunction("苏泊尔");//看到电蒸锅大类(抽象产品)里可以加一个功能,让苏泊尔给这个锅加一个。
}
运行结果:

通过调用方式可以看出,不同产品的生产由原来的总工厂变为了各个分工厂去负责。
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。
这就是一整个工厂方法。当然这样看下来估计也是懵懂的不知道它有什么作用。
我再用文字尝试说明一下:
来设想你现在需要开发一个电商平台的订单模块,其中需要生成不同类型的订单,比如普通订单、促销订单、团购订单等。每个订单里面有很多的参数。
按照常规的方式,我们直接创建每个订单类,然后全部new出来即可, 这样就没必要创建什么工厂类了对吧?
假设订单类名是OrderA、OrderB、OrderC。有很多参数的情况下New就得
OrderA A=new OrderA(参数1,参数2,.....);
要使用里面具体方法还得
A.方法1();A.方法2();........
但是现在你有各种各样的订单,这些订单是你不同的同事去开发的。如果按你上面的做法,首先你需要知道每一个订单类的情况,你需要知道要成功new出一个具体的订单类需要哪些参数、需要执行哪些方法。但是这明显是不现实的,你没有时间去看源码,甚至看不到源码。
因为你的工作只是new出订单类并调用里面的方法罢了,而每个订单类具体怎么写,其实你不需要知道,这个时候每个订单类对应一个具体的工厂类,你只需要调用工厂里的创建产品方法就行了。
再者从单依职责原则,解耦合来考虑。如果按常规new OrderA的写法,你的同事某个订单类修改了,势必会导致你写的程序会直接创建报错,你就得跟着修改。但是使用了工厂方法,根本不会影响你,因为你不参与创建实例,你的程序也不需要任何的改动。你的同事如何修改订单类跟你也没关系。
嗯.....这样说不知道有没有说明白它的作用。。。
4、抽象工厂
上面工厂模式不管工厂怎么拆分抽象,都只是针对一类产品,直接生成实例,这些工厂只生产同种类产品。
但是抽象工厂模式不同,抽象工厂模式并不直接生成实例, 而是用于对产品类簇的创建。
通俗点来讲就是:简单工厂和工厂方法模式的工作是生产产品,那么抽象工厂模式的工作就是生产工厂的。
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
抽象工厂的最大好处在于交换产品系列非常方便,只需要改变具体工厂即可使用不同的产品配置。
总的来说工厂方法模式一个工厂只生产一个产品,抽象工厂模式一个工厂生产多个产品,形成一个产品套餐,而多个工厂组成套餐系列。
4.1、抽象工厂模式的主要角色:
抽象工厂:在抽象工厂类中声明了多个工厂方法,用于返回多个产品。提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
具体产品工厂:它是抽象工厂类的子类,实现了在抽象工厂中声明的多个工厂方法,完成多个具体产品的创建。
抽象产品:它是定义一个产品的接口,定义了一个产品的规范,描述了一个产品的主要特性和功能。抽象工厂模式有多个抽象产品。
具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
4.2 创建方式
抽象工厂:有多少个系列就可以创建多少个抽象工厂类。本实例只创建了一个电器系列的工厂。里面可以有许多同系列的电器产品。
/// <summary>
///抽象工厂--电器集团,专门生产各种电器
/// </summary>
public abstract class ElectricFactory
{/// <summary>/// 生产电蒸锅/// </summary>/// <returns></returns>public abstract Electric GetElectric();/// <summary>/// 生产电饭煲/// </summary>/// <returns></returns>public abstract Rice GetRice();
}
具体工厂:同一系列可以创建多个具体的工厂,负责同一系列下的不同产品出的创建。本示例是电器下的电蒸锅和电饭煲,当然还可以电视机,烧水壶啥的。
/// <summary>/// 具体工厂-美的工厂/// </summary>public class MDFactory : ElectricFactory//美的属于该集团下的工厂{public override Electric GetElectric(){Console.WriteLine("美的生产了一个电蒸锅");return new MDElectric();//返回具体产品-美的电蒸锅}public override Rice GetRice(){Console.WriteLine("美的生产了一个电饭煲");return new MDRice();}}/// <summary>/// 具体工厂-苏泊尔工厂/// </summary>public class SBRFactory : ElectricFactory//苏泊尔属于该集团下的工厂{/// <summary>/// 实现抽象方法,具体操作在里面/// </summary>/// <returns></returns>public override Electric GetElectric()//使用集团提供的流水线{Console.WriteLine("苏泊尔生产了一个电蒸锅");return new SBRElectric();//返回具体产品-苏泊尔电蒸锅}public override Rice GetRice(){Console.WriteLine("苏泊尔生产了一个电饭煲");return new SBRRice();}}
抽象产品:有多少个不同产品就创建多少个抽象产品类。
/// <summary>/// 抽象产品电蒸锅---集团定义的电蒸锅整个品类/// </summary>public abstract class Electric{/// <summary>/// 抽象方法-定义电蒸锅有蒸东西的基本功能,具体怎么蒸就是下面的厂家决定。/// </summary>public abstract void Fun();/// <summary>/// 抽象产品提供拓展方法--子类产品非必须使用的,但可以有,就像有些电蒸锅有预约功能,有些没有。/// 而且最好是具体产品的共有的特性(公共方法),不建议是小众特性(仅适用于某个具体产品的方法),/// 例如电蒸锅的预约功能就很大众,可以有,/// 如果某个厂家要加一个烤盘功能,这就属于小众,放在具体厂家那里去实现更合适。/// </summary>public void AddFunction(string name){Console.WriteLine($"{name}加了一个预约功能");}}/// <summary>/// 抽象产品-电饭煲/// </summary>public abstract class Rice{public abstract void Fun();}
具体产品:不同产品继承不同抽象类。
/// <summary>/// 具体产品-美的电蒸锅/// </summary>public class MDElectric : Electric//这是美的电蒸锅,必须包含集团定义的电蒸锅的必备功能的同时也可以自己拓展{/// <summary>/// 具体的实现方法/// </summary>public override void Fun(){Console.WriteLine("美的电蒸锅蒸东西的功能是用大火蒸东西");}}/// <summary>/// 具体产品-苏泊尔电蒸锅/// </summary>public class SBRElectric : Electric//这是苏泊尔电蒸锅{public override void Fun(){Console.WriteLine("苏泊尔电蒸锅蒸东西的功能是用中火蒸东西");}}/// <summary>/// 具体产品-美的电饭煲/// </summary>public class MDRice : Rice//这是美的电饭煲{/// <summary>/// 具体的实现方法/// </summary>public override void Fun(){Console.WriteLine("美的电饭煲蒸东西的功能是用大火蒸东西");}}/// <summary>/// 具体产品-苏泊尔电饭煲/// </summary>public class SBRRice : Rice//这是苏泊尔电饭煲{public override void Fun(){Console.WriteLine("苏泊尔电饭煲蒸东西的功能是用中火蒸东西");}}
调用:
private void WTBtn_Click(object sender, EventArgs e){ElectricFactory electric;//创建了一个电器集团。electric = new MDFactory();//美的工厂var DZG = electric.GetElectric();//生产一个电蒸锅锅DZG.Fun();//这个锅实现具体的功能var DFB = electric.GetRice();//生产一个电饭煲DFB.Fun();//换个工厂electric = new SBRFactory();//苏泊尔工厂var DZG1 = electric.GetElectric();//生产一个电蒸锅锅DZG1.Fun();//这个锅实现具体的功能DZG1.AddFunction("苏泊尔");//看到电蒸锅大类(抽象产品)里可以加一个功能,让苏泊尔给这个锅加一个。var DFB1 = electric.GetRice();//生产一个电饭煲DFB1.Fun();}

上面实例可以看出创建一个工厂可以产出不同的产品。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
END........................................................................
相关文章:
C# 创建型设计模式----工厂模式
1 、什么是工厂模式 简单来说就是由一个对象去生成不同的对象,工厂模式是用工厂方法代替new操作的一种模式。工厂方法封装了多个相关联类的new方法,每次实例化这些类的时候不需要new多次,只需要调用工厂类的对应方法即可实例化这些类&#x…...
java中Scanner的nextLine和next方法
思考,输入1 2 3 4 5加上enter,输出什么 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int[][] m new int[2][2];for (int i 0; i < 2; i) {for (int j 0; j < 2;…...
2024年全国山洪径流模拟与洪水危险性评价技术及典型地区洪水淹没及损失分析
洪水淹没危险性(各种年遇型洪水淹没)是洪水损失评估、风险评估及洪水应急和管理规划等工作的重要基础。当前开展洪水危险性研究工作中的主要困难之一是水文资料稀缺,尤其是径流资料稀缺,既包括径流观测资料在时间上的短缺…...
CDC 同步数据需要的MySQL数据权限
授权命令如下: grant Replication client on *.* to username%; grant Replication slave on *.* to username%; flush privileges;...
Ubuntu20.04 更新Nvidia驱动 + 安装CUDA12.1 + cudnn8.9.7
一、概述 最近客户给了几台GPU服务器,长期放置落灰那种,然后想利用起来,所以上去看看了配置,系统是Ubuntu20.04,相关的驱动版本稍嫌老一些,所以需要更新Nvidia驱动,同时在安装CUDA和CUDNN,查看了显卡型号之后,打算使用onnxruntime进行推理,对比了版本,最后选择了CUD…...
算法自学 Lesson3 - 逻辑回归(LR)
目录 背景 一、适用数据集 1. 数据集选择 1.1 领域 1.2 数据集维度 1.3 记录行(样本数量) 2. 本文数据集介绍 3. 数据集下载 注意 二、逻辑回归的基本原理 1. 目的 2. Sigmoid 函数 3. 类别划分 4. 召回率 三、代码 1. 导入所需包&数…...
文件IO流
1.文件流概念 2.文件创建方式 3.常用方法 4.IO流原理 (1)InputStream,OutputStream, Reader, Writer四个都是抽象类,无法直接new, 需要由子类继承,然后new子类; (2)Reader和Writer…...
拥塞控制与TCP子问题(粘包问题,异常情况等)
拥塞控制 除了拥塞控制 以上的策越都是为了解决tcp 客户端和服务端提高效率,解决丢包的策略 但是拥塞控制是了为解决网络拥堵 出现了大面积丢包,我们发送方会判定是网络出现了问题? 丢包好解决,我们直接采用超时重传&#…...
stm32入门教程--DMA 超详细!!!
目录 简介 工作模式 1、数据转运DMA 2、ADC扫描模式DMA 简介 工作模式 1、数据转运DMA 这个例子的任务是将SRAM的数组DataA,转运到另一个数组DataB中,这个基本结构里的各个参数应该如何配置呢? 首先是外设站点和存储器站点的起始地址、…...
【使用Flask构建RESTful API】从零开始开发简单的Web服务!
使用Flask构建RESTful API:从零开始开发简单的Web服务 引言 随着Web应用程序的广泛使用,RESTful API已成为现代Web服务的核心技术之一。通过RESTful API,我们可以轻松地创建、读取、更新和删除(CRUD)数据,…...
用sdcc给51单片机编译C程序
学习单片机大部分人用的是Keil uVision,虽然好用,可大部分人用的是盗版,其实单片机程序小的话,完全可以用文本编辑器(推荐notepad)编写,然后用免费的sdcc来编译,下面介绍一下大致的过程。 sdcc…...
Java Lock LockSupport 源码
前言 相关系列 《Java & Lock & 目录》(持续更新)《Java & Lock & LockSupport & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Java & Lock & LockSupport & 总结》(学习总结/最新…...
Elasticsearch基础操作入门
阅前准备知识 学习 Elasticsearch (简称 ES) 的查询方式,建议从以下几个步骤入手: 理解 Elasticsearch 的基础概念 首先要了解 Elasticsearch 的核心概念,例如: Index(索引):相当于数据库中…...
跨域问题解决办法
跨域问题在Web开发中是一个常见的问题,特别是在前后端分离的开发模式下。以下是一些解决跨域问题的办法: 一、后端配置CORS(跨来源资源共享) CORS是一种机制,它使用额外的HTTP头来告诉浏览器一个网页的当前来源&…...
【数据结构与算法】力扣 23. 合并 K 个升序链表
题干描述 23. 合并 K 个升序链表 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 示例 1: 输入: lists [[1,4,5],[1,3,4],[2,6]] 输出: [1,1,2,3,4,4,5,6]…...
Java Lock CountDownLatch 总结
前言 相关系列 《Java & Lock & 目录》(持续更新)《Java & Lock & CountDownLatch & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Java & Lock & CountDownLatch & 总结》(学习总…...
vue+spreadjs开发
创建vue3项目 pnpm create vite --registryhttp://registry.npm.taobao.org安装spreadjs包 pnpm install "grapecity-software/spread-sheets17.1.7" "grapecity-software/spread-sheets-resources-zh17.1.7" "grapecity-software/spread-sheets-vu…...
针对初学者的PyTorch项目推荐
文章目录 1. MNIST手写数字识别2. CIFAR-10图像分类3. 图像风格迁移4. 文本生成(使用RNN)5. 简单的问答系统6. 简单的生成对抗网络(GAN)7. 简单的推荐系统 对于初学者来说,选择一些简单且具有教育意义的项目来实践PyTo…...
Helm Chart文件介绍
介绍(这个还没有完善 ,目前在找工作呢) Helm是Kubernetes的包管理器,类似于Ubuntu中的apt、CentOS中的yum或Python中的pip,可以快速查找、下载和安装软件包。Helm主要由客户端组件helm和服务端组件Tiller组成…...
1Panel 是新一代的 Linux 服务器运维管理面板
1Panel 是一款新一代的 Linux 服务器运维管理面板,旨在通过现代化的 Web 界面帮助用户轻松管理 Linux 服务器。它集成了主机监控、文件管理、数据库管理、容器管理等功能,并且支持多语言和国际化,包括英语、中文(繁体)和日语。以下是 1Panel …...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...
