【设计模式系列】抽象工厂模式

一、什么是抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。这种模式允许客户端使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,从而实现客户端与具体产品的解耦。

二、抽象工厂模式的角色

  1. 抽象产品族(Abstract Product)

    • 这是一组相关的抽象类或接口,它们定义了可能被创建的对象的公共接口。
    • 这些抽象产品通常包含在一个或多个产品等级结构中,每个产品等级结构代表一类产品。
  2. 具体产品(Concrete Product)

    • 这些是抽象产品的实现类,它们提供了抽象产品接口的具体实现。
    • 每个具体产品都是抽象产品接口的具体类,代表一个具体的对象。
  3. 抽象工厂(Abstract Factory)

    • 这是一个接口,它声明了一组方法,用于创建一系列相关的抽象产品。
    • 它不实现这些方法,而是将实现推迟到子类中。
    • 抽象工厂定义了可以被创建的产品集合,但不定义具体如何创建这些产品。
  4. 具体工厂(Concrete Factory)

    • 这些类实现了抽象工厂接口,并提供了具体工厂方法来创建具体的产品对象。
    • 每个具体工厂都对应一个产品族,它负责创建该族中的具体产品。
    • 具体工厂封装了具体产品的创建逻辑,客户端可以通过具体工厂来创建所需的产品,而无需知道具体的创建细节。

三、抽象工厂模式的典型应用场景

  1. 多系列产品创建: 当一个系统需要创建多个系列的相关产品,并且这些产品之间存在相互依赖关系时,使用抽象工厂模式可以确保客户端始终使用同一个系列的产品。

四、抽象工厂模式在Calendar中的应用

在抽象工厂模式中,Calendar 类可以被视为一个抽象工厂,它提供了创建各种具体日历实例的接口。GregorianCalendarBuddhistCalendarCalendar 类的具体实现,代表不同的日历系统。下面详细展开 Calendar 在抽象工厂模式中的应用,并给出包含 BuddhistCalendarGregorianCalendar 的代码示例。

概念解释

  • 抽象产品族(Abstract Product Family):在日历系统中,这可以是日期和时间的表示方式,包括年、月、日等。

  • 抽象产品(Abstract Product)Calendar 类本身,它定义了所有具体日历类必须实现的接口,如 getTime()setTime(Date date)get(int field) 等。

  • 具体产品(Concrete Product)GregorianCalendarBuddhistCalendar 是具体的产品类,它们实现了 Calendar 抽象类,并提供了特定日历系统的具体实现。

  • 抽象工厂(Abstract Factory)Calendar 类也可以被视为一个抽象工厂,因为它的静态方法 getInstance() 可以根据传入的 Locale 参数返回不同的 Calendar 实例。

  • 具体工厂(Concrete Factory):在这个模式中,具体工厂由 JDK 内部实现,它根据 Locale 参数决定实例化 GregorianCalendar 还是 BuddhistCalendar

//抽象工厂类
public abstract class Calendar {public static class Builder {public Builder setDate(int year, int month, int dayOfMonth) {return setFields(YEAR, year, MONTH, month, DAY_OF_MONTH, dayOfMonth);}public Builder setTimeOfDay(int hourOfDay, int minute, int second) {return setTimeOfDay(hourOfDay, minute, second, 0);}}public static Calendar getInstance(){return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));}public int getWeeksInWeekYear() {throw new UnsupportedOperationException();}
}//具体工厂类
public class GregorianCalendar extends Calendar {@Overridepublic int getWeeksInWeekYear() {GregorianCalendar gc = getNormalizedCalendar();int weekYear = gc.getWeekYear();if (weekYear == gc.internalGet(YEAR)) {return gc.getActualMaximum(WEEK_OF_YEAR);}// Use the 2nd week for calculating the max of WEEK_OF_YEARif (gc == this) {gc = (GregorianCalendar) gc.clone();}gc.setWeekDate(weekYear, 2, internalGet(DAY_OF_WEEK));return gc.getActualMaximum(WEEK_OF_YEAR);}
}//具体工厂类
public class BuddhistCalendar extends GregorianCalendar {}// 客户端
public class CalendarAbstractFactoryDemo {public static void main(String[] args) {// 创建一个默认的 GregorianCalendar 实例Calendar defaultCalendar = Calendar.getInstance();printCalendarInfo(defaultCalendar, "Default Calendar");// 创建一个 BuddhistCalendar 实例,用于泰国Locale thailandLocale = new Locale("th", "TH");Calendar thaiCalendar = Calendar.getInstance(thailandLocale);printCalendarInfo(thaiCalendar, "Thai Buddhist Calendar");}private static void printCalendarInfo(Calendar calendar, String calendarType) {// 设置日期calendar.setTime(new Date());System.out.println(calendarType + " - Year: " + calendar.get(Calendar.YEAR));System.out.println(calendarType + " - Month: " + calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.ENGLISH));System.out.println(calendarType + " - Day: " + calendar.get(Calendar.DAY_OF_MONTH));System.out.println();}
}

在这个示例中:

  • Calendar.getInstance() 方法根据提供的 Locale 参数决定创建哪种具体的 Calendar 实例。如果没有指定 Locale,它通常会创建一个 GregorianCalendar 实例,这是大多数地区的默认日历系统。
  • 当我们传递泰国的 Locale 对象给 Calendar.getInstance() 方法时,它返回一个 BuddhistCalendar 实例,这是泰国使用的日历系统。
  • printCalendarInfo() 方法打印日历的详细信息,包括年、月、日。它展示了如何使用 Calendar 实例来获取日期信息。

这个例子展示了 Calendar 类如何作为一个抽象工厂,根据不同的 Locale 参数创建不同的日历实例。这种方式使得客户端代码能够灵活地根据不同的需求创建适当的日历对象,而不需要了解具体的日历实现细节。这种设计符合抽象工厂模式的原则,提供了一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。

五、简单工厂模式与复杂工厂模式的区别

简单工厂模式和抽象工厂模式都是创建型设计模式,用于创建对象,但它们在解决问题的范围和方式上存在明显差异:

简单工厂模式

  • 解决问题的范围:简单工厂模式主要用于创建单一类型的产品。它适用于场景中对象的创建逻辑相对简单,或者需要创建的对象种类较少的情况。
  • 核心思想:简单工厂模式通过一个工厂类包含一个或多个方法,根据传入的参数来决定创建并返回哪种具体产品的实例。

抽象工厂模式

  • 解决问题的范围:抽象工厂模式用于创建多个产品族中相关或相互依赖的产品对象。它适用于场景中需要创建一系列相关或相互依赖的产品,且这些产品属于不同的产品等级结构。
  • 核心思想:抽象工厂模式定义了一个接口,用于创建一系列相关的产品,而不需要指定它们的具体类。具体工厂类实现了这个接口,并提供了创建具体产品的方法。

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

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

相关文章

VoLTE 微案例:VoLTE 注册失败,I-CSCF 返回 403,HSS(UAR) 返回 5001

目录 1. 问题描述 2. 故障注册流程与正常流程对照 3. 结论 博主wx:yuanlai45_csdn 博主qq:2777137742 想要 深入学习 5GC IMS 等通信知识(加入 51学通信),或者想要 cpp 方向修改简历,模拟面试,学习指导都可以添加博主低价指导哈。 1. 问题描述

对比迁移项目的改动

文章目录 对比迁移项目的改动场景背景解决方案 对比迁移项目的改动 场景背景 同源定制化项目,同一套代码扩展出来的项目(从领导口中得知) A项目的有三维地图展示,项目B跑起来却加载不出来,但是本地运行A项目代码&…

Unity性能优化3【内存基础篇】

1.性能、内存管理和垃圾收集的关系 先说结论,内存管理影响着游戏性能,垃圾收集是内存管理的重要部分。 当我们的游戏运行时,它使用内存来存储数据。当不再需要此数据时,存储该数据的内存将被释放,以便可以重复使用。…

vue-pc 实现内嵌式微信扫码登录(附完整代码)

一、准备工作 1. 注册微信开放平台账号 地址:([https://open.weixin.qq.com/](https://open.weixin.qq.com/)) 2. 申请开发者资质认证: 3. 创建网站应用 4. 查看应用详情,拿到 AppID 、 AppSecret 和 redirect_uri (授…

如何在服务器上部署开源大模型 GLM-4-9B-Chat 并应用到RAG应用中

本地服务器部署开源大模型有一个前提,就是得有 GPU 显卡资源,在我下面的例子中我租用了 autodl 中的算力资源,具体是租用了一张消费级别的 RTX 3090 显卡。 环境配置 操作系统及版本:ubuntu 22.04CUDA 版本: 12.1pyto…

【MATLAB源码-第263期】基于matlab的帝企鹅优化算法(EPO)无人机三维路径规划,输出做短路径图和适应度曲线.

操作环境: MATLAB 2022a 1、算法描述 帝企鹅优化算法(Emperor Penguin Optimizer,简称EPO)是一种基于自然现象的优化算法,灵感来自于帝企鹅在南极极寒环境中的生活习性。帝企鹅是一种群居动物,生活在极端…

再创佳绩 | 竹云荣获“数据要素×”大赛黑龙江分赛一等奖!

近日,由国家数据局、黑龙江省人民政府指导,黑龙江省发改委、黑龙江省数据局主办的2024年“数据要素”大赛黑龙江分赛决赛盛大召开。竹云作为联合单位参与《供热数据资产登记评价中心供热数据要素综合服务平台》项目,荣获绿色低碳赛道一等奖。…

C++ [项目] 愤怒的小鸟

现在才发现C游戏的支持率这么高,那就发几篇吧 零、前情提要 此篇为 制作,由于他没有CSDN,于是由我代发 一、基本介绍 支持Dev-C5.11版本(务必调为英文输入法),基本操作看游戏里的介绍,怎么做的……懒得说,能看懂就看注释,没有的自己猜,如果你很固执……私我吧 …

java-实例化一个List,然后添加数据的方法详解

在Java中,实例化一个 List 并向其中添加数据非常简单。List 是一个接口,因此我们通常使用它的常见实现类 ArrayList 或 LinkedList。以下是一些常见的操作方法: ### 1. 使用 ArrayList 实例化并添加数据 java import java.util.ArrayList; …

基于K8S的StatefulSet部署mysql主从

StatefulSet特性 StatefulSet的网络状态 拓扑状态:应用的多个实例必须按照某种顺序启动,并且必须成组存在,例如一个应用中必须存在一个A Pod和两个B Pod,且A Pod必须先于B Pod启动的场景 存储状态:应用存在多个实例&…

分享Vue3中的一个路由加载函数,基于Glob导入模式,根据路径自动生成路由

哈喽,大家好!我是「励志前端小黑哥」,我带着最新发布的文章又来了! 专注前端领域10年,专门分享那些没用的前端知识! 今天要分享的内容,是一段路由加载的函数代码,这段代码能自动读取…

StringBulider和StringBuffer的底层源码剖析

要深入了解 StringBuffer 和 StringBuilder 的区别,从底层源码的角度来解析,包括它们的创建、扩容机制等,可以参考 JDK 1.8 的源码。 1. AbstractStringBuilder 类 StringBuffer 和 StringBuilder 都继承自 AbstractStringBuilder。…

Three.js实现小米 su7 压缩后的模型加载

Three.js实现小米 su7 压缩后的模型加载 预览: https://threehub.cn/#/codeMirror?navigationThreeJS&classifybasic&idgltfOptLoader import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js impo…

复旦大学全球供应链研究中心揭牌,合合信息共话大数据赋能

10月13日,复旦大学全球供应链研究中心(以下简称“中心”)揭牌仪式在复旦大学管理学院政立院区隆重举行。我国的供应链体系庞大复杂,在百年未有之大变局下,保障产业链供应链安全已成为我国的重要战略目标。中心的设立旨…

《Vue3 版本差异》Vue3.5+ 在组件或HTML元素绑定 ref 差异

组件上的 ref,组合式写法的变化; 在 2024.09.03 发布的 v3.5.0 版上新增接口 useTemplateRef; v3.5 之前 代码第 8 行,导入 ref;代码第 10 行,使用 ref 传参为 null,变量名与 第三行 ref 同…

【python】sorted() list.sort()

文章目录 sorted()和list.sort()sorted 函数sorted()根据键对字典排序根据字典的键排序根据字典的值排序将排序结果转换回字典 list.sort() 方法总结 keylambda student: student[age] sorted()和list.sort() 在Python中,sorted 函数和 list.sort() 方法都可以用来…

打造企业数字化转型的未来蓝图:架构蓝图的构建与实施策略深度解析

随着数字经济的蓬勃发展,全球企业正在经历前所未有的变革与挑战。企业的运营模式、客户体验和市场竞争格局都在迅速变化。为了应对这些挑战,企业必须从战略到技术层面进行深度重塑,架构蓝图的构建和实施是数字化转型过程中不可或缺的工具。架…

CSS - grid制作表格

1. grid-template-columns:网格布局中的列的数量,也可以设置列的宽度 .grid-container {display: grid;grid-template-columns: 80px 200px auto 40px; }.grid-container {display: grid;grid-template-columns: auto auto auto auto;//表示所有列的宽度…

Starrocks部署前期准备

前提条件 硬件要求 CPU StarRocks 依靠 AVX2 指令集充分发挥其矢量化能力。因此,在生产环境中,强烈建议您将 StarRocks 部署于 x86 架构 CPU 的服务器上。 您可以在终端中运行以下命令来检查 CPU 是否支持 AVX2 指令集: cat /proc/cpuin…

高效评优:基于SpringBoot的学生奖励管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理学生评奖评优管理系统的相关信息成为必然。…