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

一、什么是抽象工厂模式

抽象工厂模式(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.rhkb.cn/news/452829.html

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

相关文章

一小时快速入门Android GPU Inspector

本文介绍如何使用 Android GPU Inspector (AGI) 对Android 应用进行系统性能分析和帧性能分析 。面向熟悉Android图形的开发者。 待分析应用需要的前置条件 (1) 将应用设置为可调试状态 <application [...] android:debuggable"true">&#xff08;2&#xff09…

LabVIEW水质监测系统

在面对全球性的海洋污染问题时&#xff0c;利用先进技术进行水质监测成为了保护海洋环境的关键手段之一。开发了一种基于LabVIEW的海洋浮标水质监测系统&#xff0c;该系统能够实时监测并评估近海水域的水质状况&#xff0c;旨在为海洋保护和污染防治提供科技支持。 项目背景 …

svn-拉取与更新代码

右键项目文件 进行更新与提交代码&#xff0c;提交代码选择更改的文件以及填写commit

电子部授课1

今天下午有院科协的授课&#xff0c;涉及电赛知识&#xff0c;单片机环境构建和模拟方向讲解。感觉要学知识还是很多呜呜呜 这是电赛讲解&#xff0c;主要是五个方面&#xff0c;有一个讲太快了没有听清哈哈哈 后面是全程搜概念的模拟&#xff0c;真的有很多知识不太明白 慌乱…

Java项目-基于springboot框架的会员制医疗预约服务管理信息系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

云曦10月13日awd复现

一、防御 1、改用户密码 passwd <user> 2、改数据库密码 进入数据库 mysql -uroot -proot 改密码 update mysql.user set passwordpassword(新密码) where userroot; 查看用户信息密码 select host,user,password from mysql.user; 改配置文件&#xff0c;将密码改为自己…

Quartus Ⅱ仿真 1.半加器

真服了&#xff0c;csdn上一搜全是收费&#xff0c;服啦服啦&#xff0c;我就自己来写一个吧 仿真波形&#xff1a; 输出结果&#xff1a; 介绍&#xff1a; 半加器&#xff08;Half Adder&#xff09;是数字电路中的一种基本组件&#xff0c;用于实现两个一位二进制数的加…

基于Leaflet和SpringBoot的全球国家综合检索WebGIS可视化

目录 前言 一、Java后台程序设计 1、业务层设计 2、控制层设计 二、WebGIS可视化实现 1、侧边栏展示 2、空间边界信息展示 三、标注成果展示 1、面积最大的国家 2、国土面积最小的国家 3、海拔最低的国家 4、最大的群岛国家 四、总结 前言 在前面的博文中&#xff…

HCIP-HarmonyOS Application Developer 习题(十五)

&#xff08;判断&#xff09;1、在HarmonyOs中发布带权限公共事件&#xff0c;发布者首先要在config.json中申请所需的权限。 答案&#xff1a;正确 分析&#xff1a;发布携带权限的公共事件&#xff1a;构造CommonEventPublishInfo对象&#xff0c;设置订阅者的权限。 &#…

[C++]ecplise C++新建项目跑hello world

测试通过版本&#xff1a; ecplise-cpp 2024-09 ecplise-cpp 2020-09 【前提】 安装好MinGW环境&#xff0c;实际测试不需要下载什么CDT插件就可以运行了。 步骤&#xff1a; &#xff08;1&#xff09;打开ecplise,选择launch 选择File->New->C/C Project 选择C M…

Win11右键默认显示更多选项

Win11默认显示 想要效果 解决方案1 先按住Shift键&#xff0c;再按右键试试。 解决方案2 1.启动命令行&#xff0c;输入命令 reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve2.显示操作成功完成&#…

基于SpringBoot+Vue+uniapp微信小程序的校园反诈骗微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

【C++复习】经典笔试题

文章目录 八大排序快排过程 卡特兰数反转链表链表的回文结构左叶子之和另一棵树的子树归并排序类与对象编程训练杨辉三角字符串乘积二叉树前序遍历成字符串数组的交集二叉树的非递归前序遍历连续子数组的最大乘积 八大排序 插冒归稳定 快排过程 以 [3,4,6,1,2,4,7] 为例&#…

《献给阿尔吉侬的花束》

这是看过的错别字最多的一本书&#xff0c;错别字多并不是这本书的缺点&#xff0c;反而是一个亮点。全书以“近步抱告”的形式讲述了想变“聪明”的查理的故事。很治愈&#xff0c;也很虐心。聪明有聪明的代价&#xff0c;看到的感受到的越多&#xff0c;需要强大的内心去承受…

jmeter中用csv data set config做参数化2

在jmeter中&#xff0c;使用csv data set config进行参数化是很重要的一个功能&#xff0c;但是这个功能的使用需要十分仔细和小心&#xff0c;因为细节之处往往决定着结果的正确与否。 举例&#xff1a; 一个登录接口用加密密码登录&#xff0c;一个登录接口用原始密码登录。…

堆的使用实例

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

vue查缺补漏

之前学习过vue基础&#xff0c;在工作上使用的时候也没有什么问题。最近在看30分钟学会Vue之核心语法,发现有一些不常用的、但挺重要的都快忘掉了&#xff0c;在此补漏一下。 搭建演示环境 创建index.html 导入 vue.min.js文件 <!DOCTYPE html> <html lang"en&…

遇到“mfc100u.dll丢失”的系统错误要怎么处理?科学修复mfc100u.dll

遇到“mfc100u.dll丢失”的系统错误会非常麻烦&#xff0c;因为mfc100u.dll是Microsoft Visual C 2010 Redistributable Package的重要部分&#xff0c;许多应用程序和游戏在运行时都需要调用这个文件。如果这个文件缺失&#xff0c;可能会导致相关软件或游戏启动失败。面对这种…

[Linux网络编程]03-TCP协议

一.TCP协议数据通信的过程 TCP数据报如下&#xff0c;数据报中的标志位双端通信的关键。 三次握手: 1.客户端向服务端发送SYN标志位&#xff0c;请求建立连接&#xff0c;同时发送空包 2.服务端向客户端回发ACK标志位(即确认标志位&#xff0c;任何一端发送数据后都需要另一端…

C++ string的精讲

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 前言 string是标准库中的一个类&#xff0c;它位于<string>头文件中。这个类提供…