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

news2024/10/21 7:33:21

一、什么是抽象工厂模式

抽象工厂模式(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 {
    @Override
    public 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_YEAR
        if (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.coloradmin.cn/o/2219890.html

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

相关文章

AUTOSAR_EXP_ARAComAPI的5章笔记(17)

☞返回总目录 相关总结:AutoSar AP CM通信组总结 5.7 通信组 5.7.1 目标 通信组(Communication Group,CG)是由 AUTOSAR 定义的复合服务模板。它提供了一个通信框架,允许在 AUTOSAR 应用程序之间以对等方式和广播模…

第6章 元素应用CSS作业

1.使用CSS对页面网页元素加以修饰&#xff0c;制作“旅游攻略”网站。 浏览效果如下&#xff1a; HTML代码如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>旅游攻略</title><link type"t…

[JAVAEE] 线程安全问题

目录 一. 什么是线程安全 二. 线程安全问题产生的原因 三. 线程安全问题的解决 3.1 解决修改操作不是原子性的问题 > 加锁 a. 什么是锁 b. 没有加锁时 c. 加锁时 d. 死锁 e. 避免死锁 3.2 解决内存可见性的问题 > volatile关键字 (易变的, 善变的) a. 不加…

【Linux】多线程安全之道:互斥、加锁技术与底层原理

目录 1.线程的互斥 1.1.进程线程间的互斥相关背景概念 1.2.互斥量mutex的基本概念 所以多线程之间为什么要有互斥&#xff1f; 为什么抢票会抢到负数&#xff0c;无法获得正确结果&#xff1f; 为什么--操作不是原子性的呢&#xff1f; 解决方式&#xff1a; 2.三种加锁…

git add操作,文件数量太多卡咋办呢,

git add介绍 Git的add命令是用于将文件或目录添加到暂存区&#xff08;也就是索引库&#xff09;&#xff0c;以便在后续的提交&#xff08;commit&#xff09;操作中一并上传到版本库的。具体来说&#xff0c;git add命令有以下几种常见用法&#xff1a; 添加单个文件&#…

4、.Net 快速开发框架:DncZeus - 开源项目研究文章

DncZeus 是一个基于 ASP.NET Core 和 Vue.js 的前后端分离的通用后台管理系统框架&#xff0c;其愿景是成为一个易于使用且功能丰富的 .NET Core 通用后台权限管理模板系统基础框架。项目名称 "DncZeus" 由 "Dnc"(.NET Core 的缩写)和 "Zeus"(古…

CLion和Qt 联合开发环境配置教程(Windows和Linux版)

需要安装的工具CLion 和Qt CLion下载链接 :https://www.jetbrains.com.cn/clion/ 这个软件属于直接默认安装就行&#xff0c;很简单&#xff0c;不多做介绍了 Qt:https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/ window 直接点exe Linux 先c…

el-table动态新增/删除表单行及校验规则

方式一&#xff1a; <template><el-form ref"ruleFormRef" :model"ruleForm" :rules"rules" label-width"120px" class"model-ruleForm":size"formSize" status-icon label-position"top">…

堆的使用实例

小伙伴们大家好&#xff0c;今天为大家带来一道算法题&#xff1a; 分析题意我们可知&#xff1a;数组最小元素一定位于0~k位置&#xff0c;如果我们首先将0~k位置构成最小堆&#xff0c;那么堆顶一定就是数组最小值。将堆顶拿出&#xff0c;将数组k1位置放入&#xff0c;那么数…

无人机+视频推流直播EasyCVR视频汇聚/EasyDSS平台在森林防护巡检中的解决方案

随着科技的飞速发展&#xff0c;无人机技术在各个领域的应用日益广泛&#xff0c;特别是在森林防护与巡检方面&#xff0c;无人机以其独特的优势&#xff0c;为传统林业管理带来了革命性的变化。本文将探讨无人机在森林防护巡检中的解决方案&#xff0c;分析其工作原理、优势及…

MYSQL 拼接函数

目录 1、CONCAT 2、CONCAT_WS 1、CONCAT 解释&#xff1a;用于拼接两个或多个字符串成一个字符串。如果任何一个参数为 NULL&#xff0c;则 CONCAT 函数的结果也会是 NULL。 语法格式&#xff1a;SELECT concat(column_name1,column_name2,...) FROM table_name 中文注释&…

【verilog刷题】时钟切换电路

时钟切换电路 1.基本概念-相关时钟源和无关时钟源2.基本的时钟切换电路&#xff08;组合逻辑&#xff09;2.相关时钟源无毛刺时钟切换电路3.非相关时钟源无毛刺时钟切换电路 1.基本概念-相关时钟源和无关时钟源 相关时钟源&#xff1a;时钟信号源之间存在某种同步或关联的关系…

[含文档+PPT+源码等]精品基于Nodejs实现的医院问诊系统的设计与实现

基于Node.js实现的医院问诊系统的设计与实现背景主要源于以下几个方面&#xff1a; 一、医疗行业变革的需求 随着互联网的飞速发展&#xff0c;特别是移动互联网技术的广泛应用&#xff0c;传统医疗行业正经历着前所未有的变革。医疗资源分布不均、患者就医难等问题日益凸显&…

数据结构单向链表的插入和删除(一)

链表 一、链表结构&#xff1a; &#xff08;物理存储结构上不连续&#xff0c;逻辑上连续&#xff1b;大小不固定&#xff09;二、单链表&#xff1a;三、单项链表的代码实现&#xff1a;四、开发可用的链表&#xff1a;四、单链表的效率分析&#xff1a; 一、链表结构&#x…

爬虫结合项目实战

由于本人是大数据专业&#xff0c;所以准备的是使用pycharm工具进行爬虫爬取数据&#xff0c;然后实现一个可视化大屏 参考项目&#xff1a; 1.医院大数据可视化最后展示 2. 大数据分析可视化系统展示 代码包&#xff1a;

如何防止SpringBoot中的jar反编译?解决相关报错及踩到的坑

目录 1. 面对的场景 2. 方案 2.1 使用代码混淆 2.2 JAR包加密 3. 项目操作 4. 启动方式 5. 踩到的各种坑 5.1 java -jar xxx-0.0.1-SNAPSHOT.jar 没有主清单属性 5.2 Caused by: java.lang.IllegalArgumentException: Unrecognized option: -pwdfxw-jar 1. 面对的场景…

sql-labs靶场第十七关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、寻找注入点 2、注入数据库 ①寻找注入方法 ②爆库&#xff0c;查看数据库名称 ③爆表&#xff0c;查看security库的所有表 ④爆列&#xff0c;查看users表的所有列 ⑤成功获取用户名…

STM32CubeMX【串口收发USART】

第一步&#xff0c;配置cubemx 配置好点右上角生成 第二步&#xff0c;串口方式 阻塞式发送 英文、中文正常、浮点有口 /* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();//配置完自动生成的 发送到串口助手上 while (1){/* USER CODE…

【计算机网络 - 基础问题】每日 3 题(五十)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

有限状态机和抽象类多态

学习有限状态机的写法&#xff0c;我们会用一个抽象类继承的方法来写 首先&#xff0c;现在我们已经用过类的继承了&#xff0c;就是在我们敌人和野猪的这个代码当中&#xff0c; 我们打开野猪的代码&#xff0c;它继承了Enemy这个父类&#xff0c;所以可以遗传它父类当中所有…