当前位置: 首页 > news >正文

C# 设计模式之抽象工厂模式

总目录


前言

工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码,而工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的可扩展性。但是在现实生活中,一个工厂只创建单个产品这样的例子很少,因为现在的工厂都多元化了,一个工厂创建一系列的产品,如果我们要设计这样的系统时,工厂方法模式显然在这里不适用,然后抽象工厂模式却可以很好地解决一系列产品创建的问题。


1 基本介绍

  1. 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个种类的产品,而抽象工厂模式可生产多个种类的产品。

  2. 抽象工厂模式的主要角色:

    • 抽象工厂
      • 在抽象工厂类中声明了多个工厂方法,用于返回多个产品。提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
    • 具体产品工厂
      • 它是抽象工厂类的子类,实现了在抽象工厂中声明的多个工厂方法,完成多个具体产品的创建。
    • 抽象产品
      • 它是定义一个产品的接口,定义了一个产品的规范,描述了一个产品的主要特性和功能。抽象工厂模式有多个抽象产品。
    • 具体产品
      • 实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
  3. 抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么。这样客户就可以从具体产品中被解耦。

  4. 抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式

2 使用场景

一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。

  • 适用于需要创建多个产品的场景
  • 抽象工厂模式一般用于严格要求以面向对象思想进行开发的超大型项目中。

3 实现方式

“绝味” 连锁店的例子来实现一个抽象工厂模式。例如,绝味鸭脖想在江西南昌和上海开分店,但是由于当地人的口味不一样,在南昌的所有绝味的东西会做的辣一点,而上海不喜欢吃辣的,所以上海的所有绝味的东西都不会做的像南昌的那样辣,然而这点不同导致南昌绝味工厂和上海的绝味工厂生成所有绝味的产品都不同,也就是某个具体工厂需要负责一系列产品(指的是绝味所有食物)的创建工作,下面就具体看看如何使用抽象工厂模式来实现这种情况。

    //抽象产品//此处为抽象鸭脖类,供不同地方的鸭脖来继承public abstract class AbstractYaBo{//展示鸭脖相关信息public abstract void Show();}//抽象产品//此处为抽象鸭舌类,供不同地方的鸭舌来继承public abstract class AbstractYaShe{public abstract void Show();}//抽象工厂//抽象工厂类,提供创建两个鸭架和鸭脖产品的接口public abstract class AbstractJueWeiFactory{// 抽象工厂提供创建一系列产品的接口// 这里作为例子,只给出了绝味中鸭脖和鸭架的生产接口public abstract AbstractYaBo MakeYaBo();public abstract AbstractYaShe MakeYaShe();}

上面我们定义了两个抽象产品类鸭架和鸭脖,然后定义了一个生产鸭脖和鸭架的抽象工厂类,现在我们需要去上海和江西南昌开分店。

上海分店:

	//上海口味的鸭脖public class ShangHaiYaBo : AbstractYaBo{public override void Show(){Console.WriteLine("上海绝味鸭脖,没那么辣");}}//上海口味的鸭舌public class ShangHaiYaShe : AbstractYaShe{public override void Show(){Console.WriteLine("上海绝味鸭舌,没那么辣");}}//上海绝味工厂 负责生产适合上海人口味的鸭脖和鸭舌public class ShangHaiJueWeiFactory : AbstractJueWeiFactory{//生产上海鸭脖public override AbstractYaBo MakeYaBo(){return new ShangHaiYaBo();}//生产上海鸭舌public override AbstractYaShe MakeYaShe(){return new ShangHaiYaShe();}}

南昌分店:

    public class NanChangYaBo : AbstractYaBo{public override void Show(){Console.WriteLine("南昌绝味鸭脖,够辣");}}public class NanChangYaShe : AbstractYaShe{public override void Show(){Console.WriteLine("南昌绝味鸭舌,够辣");}}public class NanChangJueWeiFactory : AbstractJueWeiFactory{public override AbstractYaBo MakeYaBo(){return new NanChangYaBo();}public override AbstractYaShe MakeYaShe(){return new NanChangYaShe();}}

客户端调用:

    // 客户端调用class Client{static void Main(string[] args){// 南昌工厂制作南昌的鸭脖和鸭舌AbstractJueWeiFactory nanChangFactory = new NanChangJueWeiFactory();AbstractYaBo nanChangYabo = nanChangFactory.MakeYaBo();nanChangYabo.Show();AbstractYaShe nanChangYajia = nanChangFactory.MakeYaShe();nanChangYajia.Show();// 上海工厂制作上海的鸭脖和鸭舌AbstractJueWeiFactory shangHaiFactory = new ShangHaiJueWeiFactory();shangHaiFactory.MakeYaBo().Show();shangHaiFactory.MakeYaShe().Show();Console.Read();}}

当绝味需要再在深圳再开一家分店的上海,直接按照南昌分店和上海分店一样再写一套代码就可以了。

4 优缺点分析

  • 优点

    • 抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展
    • 抽象工厂的最大好处在于交换产品系列非常方便,只需要改变具体工厂即可使用不同的产品配置。
    • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
  • 缺点

    • 抽象工厂模式很难支持新种类产品的变化。当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。

5 简单工厂,工厂方法,抽象工厂对比

  • 简单工厂,工厂方法两种模式都只是针对一类产品,直接生成实例
    但是抽象工厂模式不同,抽象工厂模式并不直接生成实例, 而是用于对产品类簇的创建。
  • 通俗点来讲就是:简单工厂和工厂方法模式的工作是生产产品,那么抽象工厂模式的工作就是生产工厂的。

简单工厂把全部的事情,在一个地方(类)全部处理完,
而工厂方法却不同,其是通过创建一个框架,然后让子类决定要如何实现。
而抽象工厂则是定义一个负责创建一组产品(也就是一个产品簇)的接口


结语

希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:
抽象工厂模式
c#中工厂模式详解

相关文章:

C# 设计模式之抽象工厂模式

总目录 前言 工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码,而工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的可扩展性。但是在现实生活中&#xff0c…...

Javascript前端面试基础(八)

window.onload和$(document).ready区别 window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕 window.onload 触发时机:window.onload 事件会在整个页面&#xf…...

R 语言学习教程,从入门到精通,R的安装与环境的配置(2)

1、R的安装与环境的配置 R语言是一款完全免费且开源的软件,它的开源许可证是GNU通用公共许可证(GPL),这意味着任何人都可以自由地使用、复制、修改和发布R语言的源代码,甚至可以将其用于商业用途。 和python等其他语言…...

Python批量下载音乐功能

Python批量下载音乐功能 Python批量下载音乐,调用API接口,同时下载歌曲和歌词 先安排一下要用的模块,导入进来。 import re import json import requests目录结构 下载音乐 Awking_Class.pymusic.txt 文件文件写的是音乐名字,使用换行分割 new_music 注意这个 ne…...

用 Bytebase 实现批量、多环境、多租户数据库的丝滑变更

Bytebase 提供了多种功能来简化批量变更管理,适用于多环境或多租户情况。本教程将指导您如何使用 部署配置 和 数据库组 在不同场景下进行数据库批量变更。 默认流水线 vs 部署配置 图片数据库 vs 数据库组 1. 准备 请确保已安装 Docker,如果本地没有重…...

java之方法引用 —— ::

目录 一、简介 二、引用静态方法 1.格式 2.示例 ​编辑 3.条件解析 三、引用成员方法 1.格式 2.示例 四、引用构造方法 1.格式 2.示例 五、类名引用成员方法 1.格式 2.略微不同的方法引用规则 3.示例 六、引用数组的构造方法 1.格式 2.示例 一、简介 方…...

「测试线排查的一些经验-上篇」 后端工程师

文章目录 端口占用脚本失灵线上部署项目结构模版配置文件生效 一般产品研发过程所使用的环境可分为: 研发环境-dev测试环境-test生产环境-prod 软件开发中,完整测试环境包括:UT、IT、ST、UAT UT Unit Test 单元测试 IT System Integration …...

AOSP12_BatteryStats统计电池数据信息

前言 BatteryStats模块主要用于设备在电池供电是系统对各个模块电量使用的统计,Android提供的Battery Historain工具就是对此模块统计的数据进行解析和展示。 一 BatteryStats模块类图 模块主要类图如下:见根目录的模块类图 BatteryStats:抽象类,本模块的核心类,主要定…...

【Android Studio】UI 布局

文章目录 view布局LinearLayout view 在Android开发中,View是一个非常重要的概念,它是所有用户界面组件的基类。View类及其子类构成了Android应用中的用户界面。每个View都占用屏幕上的一个矩形区域,并可以响应用户输入(如触摸、按…...

虚拟机Windows server忘记密码解决方法

原理 utilman.exe是Windows辅助工具管理器程序,‌虽然它本身不是一个关键的系统进程,‌但通过修改这个文件,‌用户可以访问一些有用的UI设置。‌在某些情况下,‌比如忘记密码需要重置时,‌通过修改utilman.exe文件为c…...

【香橙派系列教程】(六)嵌入式SQLite数据库

【六】嵌入式SQLite数据库 文章目录 【六】嵌入式SQLite数据库1.简介2.SQLite数据库安装3.SQLite命令用法1.创建数据库2.创建和查看表格3.插入查看数据(记录)4.删除更改数据(记录) 4.SQLite编程操作1.打开/创建数据库的C接口2.创建…...

深入探讨PHP8的新特性与性能优化

本文由 ChatMoney团队出品 随着互联网技术的飞速发展,PHP作为后端开发领域的热门语言也在不断演进。近期,PHP8的发布引起了广泛关注。本文将为您详细介绍PHP8的新特性以及性能优化,并通过具体示例帮助您更好地理解和应用这些新特性。 一、PH…...

2024年06月 Scratch 图形化(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、单选题(共10题,共30分) 第1题 运行下列程序,输入单词“PLAY”,最后角色说?( ) A:LY4AP B:AP4LY C:YA4PL D:PL4AY 答案:B 根据程序分析可知,首先获取单词字符数,然后奇数位的字母放在字符数左侧,偶数位…...

书生大模型全链路开源体系

书生大模型全链路开源体系 数据 预训练 微调 评测 部署 应用...

极简聊天室-websocket版(双向通信)

我们知道WebSocket是可以双向通信的,把极简聊天室代码又改了一下,前端发信息到后端也使用websocket,其实代码量更少了。。。 const express require(express); const app express(); var wsServer require(express-ws)(app)var msgs[];ap…...

从小白到架构师 | 缓存预热

缓存预热指的是在系统启动或上线前,提前将经常访问的数据加载到缓存中,以避免在系统刚启动时,用户大量请求直接访问数据库,导致数据库压力过大或系统性能下降。通过缓存预热,可以确保系统一上线就能提供快速的响应时间…...

Modbus -- TCP协议

MODBUS TCP协议是一种基于TCP/IP协议的Modbus变种,它允许Modbus协议在以太网网络上运行,使得设备之间可以通过IP网络交换数据。 一:协议概述 modbus_TCP协议:走的是网口,所以需要创建TCPclient对象进行通信,和modubus-RTU协议最大的区别是&a…...

python四舍五入取整数

在Python中,如果你想要对一个浮点数进行四舍五入并取整(即只保留整数部分),你可以使用内置的round()函数,但不指定第二个参数(即小数位数),或者明确指定为0。这样,Python…...

洛谷 P1868 饥饿的奶牛

原题 题目描述 有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。 现用汉语翻译为: 有 N 个区间,每个区间x,y 表示提供的x∼y 共y−x1 堆优质牧草。你可以选择任意区间但不…...

Arco Design 之Table表格

此篇文章为table表格示例&#xff0c;包含列、data数据、展开、选中、自定义等相关属性 基础表格 <a-table :columns"columns1" :data"tableData1" />const columns1 [{ title: "编号", dataIndex: "no"},{ title: "名称…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

「Java基本语法」变量的使用

变量定义 变量是程序中存储数据的容器&#xff0c;用于保存可变的数据值。在Java中&#xff0c;变量必须先声明后使用&#xff0c;声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例&#xff1a;声明与初始化 public class VariableDemo {publi…...

Cursor AI 账号纯净度维护与高效注册指南

Cursor AI 账号纯净度维护与高效注册指南&#xff1a;解决限制问题的实战方案 风车无限免费邮箱系统网页端使用说明|快速获取邮箱|cursor|windsurf|augment 问题背景 在成功解决 Cursor 环境配置问题后&#xff0c;许多开发者仍面临账号纯净度不足导致的限制问题。无论使用 16…...