C# 工厂模式

一、概述

工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在C#中,工厂模式通过定义一个公共接口或抽象类来创建对象,而具体的对象创建则由工厂类来实现。 工厂模式主要包含三个角色:

1. 抽象产品(Abstract Product):定义了产品的接口,具体产品需要实现这个接口。

2. 具体产品(Concrete Product):实现了抽象产品接口的具体类。

3. 工厂(Factory):负责创建具体产品的工厂类,通常包含一个创建产品的方法。

工厂模式的优点:

封装性:工厂模式隐藏了创建对象的细节,只需要知道创建对象的入口,而无需关注创建过程,它提供了把对象创建与对象使用分离的方法。
可扩展性:在工厂模式中,添加一个新的产品类型,只需要在工厂类中添加一个创建新产品的方法,不会影响到现有代码。
复杂对象的创建:工厂模式允许创建复杂的对象,把对象的创建过程和使用过程分开,可以使代码更容易维护。
解耦:工厂模式减少了客户端和实际产品类之间的耦合,可以独立更改实现,不会影响到其他部分。
总之,工厂模式是一种常用的对象创建型模式,具有封装性,可扩展性,复杂对象的创建和解耦等优点,适用于解决复杂对象创建问题。

工厂模式的缺点:

增加了系统复杂度:因为要把创建对象的过程抽象成接口,所以会增加系统复杂度。
父类被污染:由于工厂模式中的工厂类继承自抽象类,如果需要扩展父类的功能,可能会把父类的代码污染。
不符合开闭原则:工厂模式的实现要求修改工厂类代码,在添加新产品时可能需要修改工厂类,这不符合开闭原则。
总的来说,工厂模式虽然有一些缺点,但是它还是一种非常有用的设计模式,在很多情况下都可以帮助我们简化代码,提高代码质量。

上面这些介绍,几乎都是没什么用的文案,目的是为了做人类高质量文章,各位可以不看,当然你想看也没问题,只是看了和没看效果是一样的。

二、代码的实现

新建一个控制台项目,代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace 工厂模式
{internal class Program{static void Main(string[] args){Factory factory = new Factory();// 创建具体产品AIProduct productA = factory.CreateProduct("A");productA.Operation();  // 输出:具体产品A的操作// 创建具体产品BIProduct productB = factory.CreateProduct("B");productB.Operation();  // 输出:具体产品B的操作Console.ReadKey();}}// 抽象产品接口public interface IProduct{void Operation();}// 具体产品类Apublic class ConcreteProductA : IProduct{public void Operation(){Console.WriteLine("具体产品A的操作");}}// 具体产品类Bpublic class ConcreteProductB : IProduct{public void Operation(){Console.WriteLine("具体产品B的操作");}}// 工厂类public class Factory{public IProduct CreateProduct(string productType){switch (productType){case "A":return new ConcreteProductA();case "B":return new ConcreteProductB();default:throw new ArgumentException("无效的产品类型");}}}
}

运行:

工厂模式的代码也是非常的简单,这里就不做解析了,下面直接上一个案例吧。 

三、案例

由于工厂模式的主要作用是创建实例,那么就以公司的年会抽奖为案例吧,首先,随机设置一个抽奖人,然后由系统随机奖品,奖品有现金,手机,平板电脑,抽奖完成后,公布抽奖结果。

新建一个 Winform 项目,将项目的输入类型改为控制台输出:

别问为什么这么简单的操作你还在帖子中经常提示,上次就有人问我,你这到底是控制台项目还是 Winform 项目,也不写清楚!Winform 项目控制台打印是怎么冒出来的?

这个 Demo 的界面就两个按钮,源码我就不上传了

新建一个类 Prize,加入下面代码,下面好几个类写在一起了,我也懒的分了,反正效果是一样的

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 工厂模式案例
{/// <summary>/// 奖品的类型/// </summary>public enum PrizeType{/// <summary>/// 现金/// </summary>Money,/// <summary>/// 手机/// </summary>MobilePhone,/// <summary>/// 平板电脑/// </summary>Ipad}/// <summary>/// 奖品/// </summary>public abstract class Prize{/// <summary>/// 数量/// </summary>public int Number { get; set; }/// <summary>/// 获奖人/// </summary>public string Awardee { get; set; }/// <summary>/// 奖品类型/// </summary>public PrizeType PrizeTypes { get; set; }/// <summary>/// 随机数/// </summary>public Random Randoms { get; private set; } = new Random();/// <summary>/// 操作/// </summary>public abstract void Operation();/// <summary>/// 设置获奖人/// </summary>/// <param name="Awardee"></param>public abstract void SetAwardee(string Awardee);}/// <summary>/// 现金/// </summary>public class Money : Prize{public override void Operation(){Number = Randoms.Next(100, 1000);PrizeTypes =  PrizeType.Money;Console.WriteLine("得到奖品 类型:{0},数量是:{1}", PrizeTypes, Number);}public override void SetAwardee(string awardee){Awardee = awardee;Console.WriteLine("当前奖品的获得者是:{0}", awardee);}}/// <summary>/// 手机/// </summary>public class MobilePhone : Prize{public override void Operation(){Number = Randoms.Next(1, 3);PrizeTypes = PrizeType.MobilePhone;Console.WriteLine("得到奖品 类型:{0},数量是:{1}", PrizeTypes, Number);}public override void SetAwardee(string awardee){Awardee = awardee;Console.WriteLine("当前奖品的获得者是:{0}", awardee);}}/// <summary>/// 平板电脑/// </summary>public class Ipad : Prize{public override void Operation(){Number = Randoms.Next(1, 3);PrizeTypes = PrizeType.Ipad;Console.WriteLine("得到奖品 类型:{0},数量是:{1}", PrizeTypes, Number);}public override void SetAwardee(string awardee){Awardee = awardee;Console.WriteLine("当前奖品的获得者是:{0}", awardee);}}public class Factory{public static Prize CreateProduct(PrizeType prizeType){switch (prizeType){case PrizeType.Money:return new Money();case PrizeType.MobilePhone:return new MobilePhone();case PrizeType.Ipad:return new Ipad();default:return null;}}private Factory() { }}
}

Form1 的代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace 工厂模式案例
{public partial class Form1 : Form{public Form1(){InitializeComponent();}//随机数private Random Randoms = new Random();//抽奖人列表private List<string> NameList = new List<string>() { "张三", "李四", "老王", "柱子", "狗剩", "铁蛋" };//当前的抽奖人private string Awardee = string.Empty;//奖品类型枚举的长度private int PrizeTypeCount = 0;private void Form1_Load(object sender, EventArgs e){PrizeTypeCount = System.Enum.GetNames(new PrizeType().GetType()).Length;}//抽奖人private void button1_Click(object sender, EventArgs e){int index = Randoms.Next(0, NameList.Count);Awardee = NameList[index];Console.WriteLine("当前的抽奖人是:{0}", Awardee);}//抽奖private void button2_Click(object sender, EventArgs e){if (string.IsNullOrEmpty(Awardee)){Console.WriteLine("请先确认抽奖人");return;}int index = Randoms.Next(0, PrizeTypeCount);PrizeType prizeType = (PrizeType)index;Prize prize = Factory.CreateProduct(prizeType);prize.Operation();prize.SetAwardee(Awardee);}}
}

运行:

这样,一个简单的抽奖系统就实现了,写的也不一定是最合适的案例,有什么需要指正的,欢迎留言评论。

end

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

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

相关文章

【C++数据结构】二叉搜索树

【C数据结构】二叉搜索树 目录 【C数据结构】二叉搜索树二叉搜索树概念二叉搜索树操作二叉搜索树的查找二叉搜索树的插入二叉搜索树的删除二叉搜索树的实现二叉搜索树的应用二叉搜索树的性能分析 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.8.22 前言&#xff1a;二…

无涯教程-PHP - preg_split()函数

preg_split() - 语法 array preg_split (string pattern, string string [, int limit [, int flags]]); preg_split()函数的操作与split()完全相同&#xff0c;只不过正则表达式被接受为pattern的输入参数。 如果指定了可选的输入参数limit&#xff0c;则仅返回子字符串的限…

WebGL 变量uniform、gl.getUniformLocation、gl.uniform4f及其同族函数相关

目录 uniform变量命名规范 获取 uniform 变量的存储地址 gl.getUniformLocation 向uniform变量赋值 gl.uniform4f ​编辑 gl.uniform4f()的同族函数 demo&#xff1a;点击webgl坐标系的四个象限绘制各自不同颜色的点 uniform变量命名规范 var FSHADER_SOURCE uniform vec4…

小程序-基于vant的Picker组件实现省市区选择

一、原因 因vant/area-data部分的市/区数据跟后台使用的高德/腾讯省市区有所出入&#xff0c;故须保持跟后台用同一份数据&#xff0c;所以考虑以下几个组件 1、Area 2、Cascader 3、Picker 因为使用的是高德地图的省市区json文件&#xff0c;用area的话修改结构代价太大&…

AVL——平衡搜索树

✅<1>主页&#xff1a;我的代码爱吃辣&#x1f4c3;<2>知识讲解&#xff1a;数据结构——AVL树☂️<3>开发环境&#xff1a;Visual Studio 2022&#x1f4ac;<4>前言&#xff1a;AVL树是对二叉搜索树的严格高度控制&#xff0c;所以AVL树的搜索效率很高…

xargs 的用法 在1个文件夹中批量删除文件,这些删除的文件名是另一个文件夹中的文件名。

xargs 的用法 在1个文件夹中批量删除文件&#xff0c;这些删除的文件名是另一个文件夹中的文件名。 1、问题背景 应用场景 1、问题背景 应用场景 在二进制部署docker时&#xff0c;会把docker的所有可执行文件复制到/usr/bin下。 如果说复制过去后&#xff0c;想要反悔&#x…

VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库

前面说的Delphi通过Activex DLL同时调用PowerBasic和FreeBasic写的DLL&#xff0c;是在WINDOWS基础平台上完成的。 而 .NET平台是架在WINDOWS基础平台之上的&#xff0c;它的上面VB.NET或C#等开发的APP程序&#xff0c;下面写一下用VB.NET&#xff0c;通过VB6注册的Activex DLL…

一文速学-让神经网络不再神秘,一天速学神经网络基础(一)

前言 思索了很久到底要不要出深度学习内容&#xff0c;毕竟在数学建模专栏里边的机器学习内容还有一大半算法没有更新&#xff0c;很多坑都没有填满&#xff0c;而且现在深度学习的文章和学习课程都十分的多&#xff0c;我考虑了很久决定还是得出神经网络系列文章&#xff0c;…

C语言刷题(13)

第一题 第二题 第三题 第四题 第五题 第六题 第七题 注意 1.nsqrt(n)&#xff0c;sqrt本身不会将n开根 2.初始化已经令sumn了&#xff0c;故相加的个数为m-1次

K8S用户管理体系介绍

1 K8S账户体系介绍 在k8s中&#xff0c;有两类用户&#xff0c;service account和user&#xff0c;我们可以通过创建role或clusterrole&#xff0c;再将账户和role或clusterrole进行绑定来给账号赋予权限&#xff0c;实现权限控制&#xff0c;两类账户的作用如下。 server acc…

小航助学GESP_C++一级模拟测试卷第2套(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSD…

大学生创业出路【第二弹】科创训练营

目录 &#x1f680;一、我从哪里了解到的训练营 &#x1f680;二、训练营里学习和日常 &#x1f50e;学习 &#x1f50e;环境和设备 &#x1f50e;遇到的人 &#x1f50e;团队记录视频 &#x1f680;三、感悟 ​​​​个人主页&#xff1a;一天三顿-不喝奶茶&#x1f39…

JVM元空间溢出的排除思路

背景&#xff1a; java的应用我们为了防止元空间的无限扩展&#xff0c;一般都会设置MaxMetaSpace参数&#xff0c;一般来说只要这个值是512M或者1G左右就足够了&#xff0c;不过今天遇到一个meta空间溢出问题&#xff0c;简单记录下排除的思路 meta元空间溢出 最开始的现象…

实验六 u-boot-2013.01移植

【实验目的】 了解u-boot 的代码结构及移植的基本方法 【实验环境】 ubuntu 14.04发行版FS4412实验平台交叉编译工具arm-none-linux-gnueabi- 【注意事项】 实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行 【实验步骤】 一、建立自己的平台 下载uboot源码 在uboo…

【网络】DNS | ICMP | NAT | 代理服务器

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 前面几篇文章虽然讲介绍了整个网络通信的协议栈&#xff0c;我们也知道了完整的网络通信过程&#xff…

【⑬MySQL | 数据类型(一)】简介 | 整数 | 浮点 | 定点类型

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL数据类型简介 | 整数 | 浮点 | 定点类型的分享✨ 目录 前言0.数据类型简介1 整数类型2 浮点类型3 定点类型4 日期/时间类型总结 0.数据类型简介 数据类型&#xff08;data_type&#xff09;是指系统中所允许的…

LRU淘汰策略执行过程

1 介绍 Redis无论是惰性删除还是定期删除&#xff0c;都可能存在删除不尽的情况&#xff0c;无法删除完全&#xff0c;比如每次删除完过期的 key 还是超过 25%&#xff0c;且这些 key 再也不会被客户端访问。 这样的话&#xff0c;定期删除和堕性删除可能都彻底的清理掉。如果…

百度许少辉著Baidu《乡村振兴战略下传统村落文化旅游设计》图书馆新书通报

百度许少辉著Baidu《乡村振兴战略下传统村落文化旅游设计》图书馆新书通报

AWS SDK 3.x for .NET Framework 4.0 可行性测试

前言 为了应对日益增长的网络安全挑战, 越来越多的互联网厂商已经陆续开始或者已经彻底停止了对 SSL 3 / TLS 1.0 / TLS1.1 等上古加密算法的支持. 而对于一些同样拥有悠久历史的和 AWS 服务相关联的应用程序, 是否可以通过仅更新 SDK 版本的方式来适应新的环境. 本文将以 Win…

揭开pkill的秘密:在Linux中杀死进程的完整指南

揭开pkill的秘密&#xff1a;在Linux中杀死进程的完整指南 一、前言二、进程管理基础知识2.1、什么是进程&#xff1f;2.2、进程管理的原理和目的2.3、进程状态和标识符 三、理解Linux pkill命令3.1、pkill命令的概述和作用3.2、与kill命令的对比3.3、常见的pkill命令选项和参数…