C#的简单工厂模式、工厂方法模式、抽象工厂模式

工厂模式是一种创建型设计模式,主要将对象的创建和使用分离,使得系统更加灵活和可维护。常见的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式,以下是 C# 实现的三个案例:

简单工厂模式

简单工厂模式通过一个工厂类来创建对象,而不需要把客户端代码与具体类的实现细节绑定在一起。

using System;// 1. 定义产品接口
public interface IProduct
{void Use();
}// 2. 创建具体产品类
public class ConcreteProductA : IProduct
{public void Use(){Console.WriteLine("using ConcreteProductA");}
}public class ConcreteProductB : IProduct
{public void Use(){Console.WriteLine("using ConcreteProductB");}
}// 3. 创建工厂类
public class ProductFactory
{public static IProduct CreateProduct(string type){switch (type){case "a":return new ConcreteProductA();case "b":return new ConcreteProductB();default:throw new ArgumentException("unknown product type");}}
}// 4. 运用业务代码
class Program
{static void Main(string[] args){IProduct productA = ProductFactory.CreateProduct("a");productA.Use();IProduct productB = ProductFactory.CreateProduct("b");productB.Use();}
}

代码解析

  • 定义了一个 IProduct 接口,其中包含 Use 方法,这是所有具体产品类需要实现的功能。
  • ConcreteProductA 和 ConcreteProductB 是具体的产品类,它们实现了 IProduct 接口,分别实现了自己的 Use 方法。
  • ProductFactory 是工厂类,它的静态方法 CreateProduct 根据传入的参数(这里是字符串)来决定创建并返回哪个具体产品类的实例。
  • 在 Main 方法中,应用业务代码通过调用 ProductFactory.CreateProduct 方法来获取产品实例,而不需要关心具体的创建过程,降低了客户端与具体产品类的耦合度。

工厂方法模式

工厂方法模式将对象的创建放在一个接口中,但让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。

using System;// 1. 定义产品接口
public interface IProduct
{void Use();
}// 2. 创建具体产品类
public class ConcreteProductA : IProduct
{public void Use(){Console.WriteLine("using ConcreteProductA");}
}public class ConcreteProductB : IProduct
{public void Use(){Console.WriteLine("using ConcreteProductB");}
}// 3. 定义抽象工厂类
public abstract class ProductFactory
{public abstract IProduct CreateProduct();
}// 4. 创建具体工厂类
public class ConcreteProductAFactory : ProductFactory
{public override IProduct CreateProduct(){return new ConcreteProductA();}
}public class ConcreteProductBFactory : ProductFactory
{public override IProduct CreateProduct(){return new ConcreteProductB();}
}// 5. 运用业务代码
class Program
{static void Main(string[] args){ProductFactory factoryA = new ConcreteProductAFactory();IProduct productA = factoryA.CreateProduct();productA.Use();ProductFactory factoryB = new ConcreteProductBFactory();IProduct productB = factoryB.CreateProduct();productB.Use();}
}

代码解析

  • 同样先定义了 IProduct 接口和两个具体的产品类 ConcreteProductAConcreteProductB
  • 新增了一个抽象工厂类 ProductFactory,其中包含一个抽象方法 CreateProduct,用于创建产品实例。
  • ConcreteProductAFactory 和 ConcreteProductBFactory 是具体的工厂类,它们继承自 ProductFactory 并实现了 CreateProduct 方法,分别负责创建 ConcreteProductA 和 ConcreteProductB 的实例。
  • 在应用业务代码中,通过创建不同的具体工厂类实例,调用其 CreateProduct 方法来获取对应的产品实例。这种方式符合开闭原则,当需要增加新的产品时,只需要新增对应的产品类和工厂类,而无需修改现有的工厂类代码。

抽象工厂模式

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

using System;// 1. 定义抽象产品接口1
public interface ICar
{void Drive();
}// 2. 定义抽象产品接口2
public interface IMotorcycle
{void Ride();
}// 3. 创建具体产品类 - 汽车
public class HondaCar : ICar
{public void Drive(){Console.WriteLine("Driving Honda Car");}
}public class ToyotaCar : ICar
{public void Drive(){Console.WriteLine("Driving Toyota Car");}
}// 4. 创建具体产品类 - 摩托车
public class HondaMotorcycle : IMotorcycle
{public void Ride(){Console.WriteLine("Riding Honda Motorcycle");}
}public class ToyotaMotorcycle : IMotorcycle
{public void Ride(){Console.WriteLine("Riding Toyota Motorcycle");}
}// 5. 定义抽象工厂接口
public interface IAutoFactory
{ICar CreateCar();IMotorcycle CreateMotorcycle();
}// 6. 创建具体工厂类
public class HondaFactory : IAutoFactory
{public ICar CreateCar(){return new HondaCar();}public IMotorcycle CreateMotorcycle(){return new HondaMotorcycle();}
}public class ToyotaFactory : IAutoFactory
{public ICar CreateCar(){return new ToyotaCar();}public IMotorcycle CreateMotorcycle(){return new ToyotaMotorcycle();}
}// 7. 应用业务代码
class Program
{static void Main(string[] args){IAutoFactory hondaFactory = new HondaFactory();ICar hondaCar = hondaFactory.CreateCar();IMotorcycle hondaMotorcycle = hondaFactory.CreateMotorcycle();hondaCar.Drive();hondaMotorcycle.Ride();IAutoFactory toyotaFactory = new ToyotaFactory();ICar toyotaCar = toyotaFactory.CreateCar();IMotorcycle toyotaMotorcycle = toyotaFactory.CreateMotorcycle();toyotaCar.Drive();toyotaMotorcycle.Ride();}
}

代码解析

  • 定义了两个抽象产品接口 ICar 和 IMotorcycle,分别表示汽车和摩托车产品的行为。
  • 创建了多个具体产品类,如 HondaCarToyotaCarHondaMotorcycleToyotaMotorcycle,它们分别实现对应的抽象产品接口。
  • 抽象工厂接口 IAutoFactory 声明了两个创建产品的方法 CreateCar 和 CreateMotorcycle,用于创建汽车和摩托车。
  • HondaFactory 和 ToyotaFactory 是具体的工厂类,实现了 IAutoFactory 接口,负责创建对应品牌的汽车和摩托车实例。
  • 在应用业务代码中,通过选择不同的具体工厂类,可以创建出不同品牌的汽车和摩托车产品,并且这些产品之间是相关联的,比如都是同一品牌下的不同类型交通工具。 当需要增加新的品牌或产品类型时,需要修改抽象工厂接口和所有具体工厂类,这是抽象工厂模式的一个缺点,但它可以确保创建出来的一系列产品的一致性。

简单工厂模式

  • 优点
    • 实现简单:模式结构简单,易于理解和实现,适合初学者快速上手和小型项目开发。
    • 解耦对象创建和使用:将对象创建逻辑封装在工厂类中,客户端无需了解具体创建过程,只需与工厂类交互获取对象,降低了客户端与具体产品类的耦合度。
    • 便于代码维护:当创建对象的逻辑发生变化时,只需修改工厂类,而无需改动客户端代码,在一定程度上方便了维护。
  • 缺点
    • 违背开闭原则:当需要增加新的产品类型时,必须修改工厂类的代码来添加新的创建逻辑,这可能会引入新的错误,并且违反了软件设计中对扩展开放、对修改关闭的开闭原则。
    • 工厂类职责过重:随着产品种类不断增加,工厂类中的条件判断逻辑会变得越来越复杂,导致工厂类难以维护和理解,不符合单一职责原则。
  • 应用场景
    • 产品种类较少且稳定:当项目中需要创建的对象种类较少,且后期很少会有新增产品类型的情况时,简单工厂模式可以很好地简化对象的创建过程。
    • 需求变化不大:如果业务需求相对稳定,对软件的扩展性要求不高,使用简单工厂模式可以快速实现对象的创建管理。

工厂方法模式

  • 优点
    • 符合开闭原则:新增产品时,只需创建新的具体产品类和对应的具体工厂类,无需修改现有代码,提高了系统的扩展性和可维护性。
    • 责任明确:每个具体工厂类只负责创建一种具体产品,符合单一职责原则,使得代码结构更加清晰,便于理解和维护。
    • 解耦程度高:客户端只与抽象工厂类和抽象产品类交互,具体产品的创建过程被完全封装在具体工厂类中,进一步降低了客户端与具体产品的耦合度。
  • 缺点
    • 类数量增多:每增加一种产品,就需要增加一个具体产品类和一个具体工厂类,导致系统中的类数量快速增加,增加了代码的复杂性和管理成本。
    • 理解难度增加:由于引入了抽象工厂类和多个具体工厂类,相比简单工厂模式,工厂方法模式的结构更加复杂,需要开发者花费更多时间来理解和掌握。
  • 应用场景
    • 产品不断扩展:适用于产品种类会不断增加和变化的场景,例如电商系统中商品类型的不断扩充。
    • 创建逻辑多样化:当不同产品的创建逻辑差异较大时,工厂方法模式可以将不同的创建逻辑分别封装在各自的具体工厂类中,使代码更加清晰。

抽象工厂模式

  • 优点
    • 高度解耦:客户端通过抽象工厂接口获取产品,与具体产品类和具体工厂类的实现细节完全解耦,提高了系统的独立性和可维护性。
    • 方便维护产品族:可以轻松地创建一系列相关或相互依赖的产品对象,即产品族,保证了产品族中各个产品之间的一致性和完整性,便于对产品族进行统一管理和维护。
    • 易于切换产品族:在运行时可以很方便地切换不同的具体工厂,从而获取不同产品族的对象,增强了系统的灵活性和可扩展性。
  • 缺点
    • 结构复杂:抽象工厂模式涉及多个抽象产品类、具体产品类、抽象工厂类和具体工厂类,结构较为复杂,增加了系统的理解和实现难度。
    • 维护成本高:当产品族中需要增加新的产品时,不仅需要修改抽象工厂接口,还需要修改所有具体工厂类,维护成本较高,违背了开闭原则。
  • 应用场景
    • 创建相关产品族:适用于需要创建一系列相互关联或依赖的对象的场景,如游戏开发中创建不同主题风格的角色、场景和道具等产品族。
    • 跨平台开发:在开发跨平台应用程序时,不同平台(如 Windows、Mac、Linux 等)有各自的界面组件(按钮、文本框等),可以使用抽象工厂模式为每个平台创建对应的产品族,实现界面的统一管理和切换。

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

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

相关文章

python基础8 单元测试

通过前面的7个章节,作者学习了python的各项基础知识,也学习了python的编译和执行。但在实际环境上,我们需要验证我们的代码功能符合我们的设计预期,所以需要结合python的单元测试类,编写单元测试代码。 Python有一个内…

算法刷题力扣

先把大写的字母变成小写的&#xff0c;用大写字母32即可变为小写字母。 写循环跳过字符。 然后判断是否相等即可。具体代码如下&#xff1a; class Solution { public: bool isPalindrome(string s) { int sizes.size(); int begin0; int ends.size()-1; for(int i0;i<s…

allure下载安装及配置

这里写目录标题 一、JDK下载安装及配置二、allure下载三、allure安装四、allure环境变量配置五、allure验证是否安装成功 一、JDK下载安装及配置 allure 是一个java测试报告框架。所以要基于JDK环境。 JDK下载与安装及配置&#xff1a;https://blog.csdn.net/qq_24741027/arti…

linux之 内存管理(1)-armv8 内核启动页表建立过程

一、内核启动时&#xff0c;页表映射有哪些&#xff1f; Linux初始化过程&#xff0c;会依次建立如下页表映射&#xff1a; 1.恒等映射&#xff1a;页表基地址idmap_pg_dir; 2.粗粒度内核镜像映射&#xff1a;页表基地址init_pg_dir; 3.fixmap映射&#xff1a;页表基地址为…

【面试问题】Java 接口与抽象类的区别

引言 在 Java 面向对象编程中&#xff0c;接口&#xff08;Interface&#xff09;和抽象类&#xff08;Abstract Class&#xff09;是两个重要的抽象工具。它们都能定义未实现的方法&#xff0c;但设计目标和使用场景截然不同。本文将通过语法、特性和实际案例&#xff0c;深入…

【资料分享】全志科技T113-i全国产(1.2GHz双核A7 RISC-V)工业核心板规格书

核心板简介 创龙科技SOM-TLT113 是一款基于全志科技T113-i 双核ARM Cortex-A7 玄铁C906 RISC-V HiFi4 DSP 异构多核处理器设计的全国产工业核心板&#xff0c;ARM Cortex-A7 处理单元主频高达1.2GHz。核心板 CPU、ROM、RAM、电源、晶振等所有元器件均采用国产工业级方案&…

R语言高效数据处理-自定义格式EXCEL数据输出

注&#xff1a;以下代码均为实际数据处理中的笔记摘录&#xff0c;所以很零散&#xff0c; 将就看吧&#xff0c;这一篇只是代表着我还在&#xff0c;所以可能用处不大&#xff0c;这一段时间都很煎熬&#xff01; 在实际数据处理中为了提升效率&#xff0c;将Excel报表交付给…

LeetCode 30 —— 30.串联所有单词的子串

题目&#xff1a; 给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。 注意子串要与 words 中的单词完全匹配&#xff0c;中间不能有其他字符&#xff0c;但不需要考虑 words 中单词串联的顺序。 示例 1&#xff…

《算法笔记》9.2小节——数据结构专题(2)->二叉树的遍历 问题 A: 复原二叉树(同问题 C: 二叉树遍历)

题目描述 小明在做数据结构的作业&#xff0c;其中一题是给你一棵二叉树的前序遍历和中序遍历结果&#xff0c;要求你写出这棵二叉树的后序遍历结果。 输入 输入包含多组测试数据。每组输入包含两个字符串&#xff0c;分别表示二叉树的前序遍历和中序遍历结果。每个字符串由…

SpringBoot-2整合MyBatis以及基本的使用方法

目录 1.引入依赖 2.数据库表的创建 3.数据源的配置 4.编写pojo类 5.编写controller类 6.编写接口 7.编写接口的实现类 8.编写mapper 1.引入依赖 在pom.xml引入依赖 <!-- mysql--><dependency><groupId>com.mysql</groupId><artifac…

Unity Shader Graph高级节点逻辑设计:程序化噪声生成技术详解

一、程序化噪声的核心价值 程序化噪声生成是Shader开发中的关键核心技术&#xff0c;通过数学算法直接生成纹理信息&#xff0c;相较于传统位图纹理具有以下优势&#xff1a; 无限分辨率&#xff1a;可动态适应任意显示精度 参数化控制&#xff1a;实时调整噪声频率、振幅等属…

[蓝桥杯 2023 省 B] 飞机降落(不会dfs的看过来)

[蓝桥杯 2023 省 B] 飞机降落 题目描述 N N N 架飞机准备降落到某个只有一条跑道的机场。其中第 i i i 架飞机在 T i T_{i} Ti​ 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 D i D_{i} Di​ 个单位时间&#xff0c;即它最早可以于 T i T_{i} Ti​ 时刻…

英伟达GTC 2025大会产品全景剖析与未来路线深度洞察分析

【完整版】3月19日&#xff0c;黄仁勋Nvidia GTC 2025 主题演讲&#xff5c;英伟达 英伟达GTC 2025大会产品全景剖析与未来路线深度洞察分析 一、引言 1.1 分析内容 本研究主要采用了文献研究法、数据分析以及专家观点引用相结合的方法。在文献研究方面&#xff0c;广泛收集了…

强化学习 - PPO控制无人机

PPO&#xff08;Proximal Policy Optimization&#xff0c;近端策略优化&#xff09;是一种强化学习算法&#xff0c;用于训练智能体&#xff08;无人机&#xff09;如何在环境中做出决策。它本质上是 策略梯度&#xff08;Policy Gradient&#xff09;方法 的一种改进&#xf…

YOLO11报错:AttributeError: module ‘torch‘ has no attribute ‘OutOfMemoryError‘

事情是这样的&#xff1a;前几天YOLO11的代码还是可以训练的&#xff0c;昨天训练了一天&#xff0c;今天换模型就报这个错。 AttributeError: module torch has no attribute OutOfMemoryError我查了一下&#xff1a;YOLO11官方代码issues里面也有人有同样的问题&#xff0c;…

Prometheus使用

介绍&#xff1a;Prometheus 是一个开源的 监控与告警系统&#xff0c;主要用于采集和存储时间序列数据&#xff08;Time Series Data&#xff09; Prometheus的自定义查询语言PromQL Metric类型 为了能够帮助用户理解和区分这些不同监控指标之间的差异&#xff0c;Prometheu…

ESG报告评级标准解读

ESG&#xff08;环境、社会、治理&#xff09;报告评级标准用于评估企业在环境、社会和公司治理方面的表现。以下是主要评级标准的解读&#xff1a; 1. 环境&#xff08;Environmental&#xff09; 碳排放&#xff1a;评估企业的温室气体排放及减排措施。 能源使用&#xff1…

清晰易懂的 PHP 安装与配置教程

初学者也能看懂的 PHP 安装与配置教程 本教程将手把手教你如何在 Windows 系统上安装 PHP&#xff0c;并配置 Composer&#xff08;PHP 的依赖管理工具&#xff09;的缓存位置&#xff0c;即使你是零基础小白&#xff0c;也能轻松完成&#xff01; 一、准备工作 操作系统&…

Zabbix监控自动化(Zabbix Mnitoring Automation)

​​​​​​zabbix监控自动化 1、自动化监控(网络发现与自动注册只能用其一) 1.1 ansible安装zabbix agent 新采购100台服务器&#xff1a; 1、安装操作系统 2、初始化操作系统 3、安装zabbix agent 1.手动部暑 2.脚本部暑(shell expect) 3.ansible 4、纳入监控 1.…

Android Launcher3 首屏图标锁定技术方案解析

一、需求背景与技术挑战 在Android 13系统定制开发中&#xff0c;需实现Launcher首屏图标固定功能。该需求需在以下技术维度进行突破&#xff1a; 拖拽事件拦截机制&#xff1a;需精准识别拖拽目标区域 布局层级判定&#xff1a;准确识别第一屏的布局标识 跨屏操作限制&…