Java二十三种设计模式-抽象工厂模式(3/23)

抽象工厂模式:复杂系统的灵活构建者

引言

在软件开发中,抽象工厂模式是一种提供接口以创建相关或依赖对象族的创建型设计模式。这种模式允许客户端使用一个共同的接口来创建不同的产品族,而无需指定具体类。

基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

第一部分:抽象工厂模式概述

1.1 定义与目的

抽象工厂模式的基本定义

抽象工厂模式是一种创建型设计模式,用于创建一系列相关或相互依赖的对象,而不需要指定它们具体的类。这种模式提供了一个接口,用于生成一组相关的对象,而客户端不需要知道这些对象的具体类。

解释为何需要抽象工厂模式

在复杂的系统中,对象的创建可能会涉及到多个相关的类,这些类之间可能存在一定的依赖关系。如果直接在客户端代码中创建这些对象,会导致客户端与具体类紧密耦合,难以扩展和维护。抽象工厂模式通过提供一个抽象的创建接口,将对象的创建过程封装起来,使得系统更加灵活和易于扩展。

1.2 组成元素

抽象工厂(Abstract Factory)

  • 定义了创建一系列相关或依赖对象的接口。
  • 它是一个抽象角色,不实现具体的创建逻辑。

具体工厂(Concrete Factory)

  • 实现了抽象工厂的接口,生成具体的产品对象。
  • 每个具体工厂都对应一个产品族。

抽象产品(Abstract Product)

  • 定义了产品的接口,是所有具体产品类的共同父类。
  • 它是一个抽象角色,不实现具体的产品类。

具体产品(Concrete Product)

  • 实现了抽象产品的接口,是抽象工厂模式中被创建的具体对象。
  • 每个具体产品都属于一个产品族。

客户端(Client)

  • 使用抽象工厂来请求创建对象,与具体工厂和具体产品解耦。
  • 客户端通过抽象工厂的接口与具体工厂交互,从而获得所需的产品。

角色之间的关系

  • 抽象工厂与具体工厂:具体工厂实现了抽象工厂的接口,负责创建具体的产品。
  • 抽象产品与具体产品:具体产品实现了抽象产品的接口,是系统中实际使用的对象。
  • 客户端与抽象工厂:客户端通过抽象工厂的接口请求产品,而不直接与具体工厂或具体产品交互。

抽象工厂模式的核心优势在于其封装性、灵活性和可扩展性。通过使用抽象工厂模式,可以在不修改现有代码的基础上,引入新的产品族,满足开闭原则。在下一部分中,我们将通过Java代码示例来展示抽象工厂模式的具体实现。

 

第二部分:抽象工厂模式实现

2.1 Java实现示例

以下是使用Java语言实现抽象工厂模式的一个示例。假设我们有一个形状和颜色的工厂,它们可以生成多种类型的形状和颜色。

// 抽象产品:形状
interface Shape {void draw();
}// 具体产品:圆形
class Circle implements Shape {public void draw() {System.out.println("Drawing a Circle");}
}// 抽象产品:颜色
interface Color {void fill();
}// 具体产品:红色
class Red implements Color {public void fill() {System.out.println("Filling with Red Color");}
}// 抽象工厂
interface Factory {Shape getShape();Color getColor();
}// 具体工厂:形状和颜色工厂
class ShapeColorFactory implements Factory {private String colorType;public ShapeColorFactory(String colorType) {this.colorType = colorType;}@Overridepublic Shape getShape() {return new Circle(); // 假设这个工厂只能生成圆形}@Overridepublic Color getColor() {if ("Red".equalsIgnoreCase(colorType)) {return new Red();}return new Color() { // 默认颜色public void fill() {System.out.println("Filling with Default Color");}};}
}// 客户端代码
public class Client {public static void main(String[] args) {Factory factory = new ShapeColorFactory("Red");Shape shape = factory.getShape();shape.draw();Color color = factory.getColor();color.fill();}
}

2.2 设计原则与模式应用

抽象工厂模式如何体现设计原则

开闭原则

抽象工厂模式遵循开闭原则,即软件实体应对扩展开放,对修改封闭。当需要添加新的形状或颜色时,我们只需添加相应的具体产品类和具体工厂类,而无需修改现有的抽象工厂和客户端代码。

里氏替换原则

在抽象工厂模式中,具体工厂实现了抽象工厂的接口,确保了具体产品能够替换其抽象产品。这意味着客户端可以接收任何从抽象工厂派生的实例,并期待它仍然有效。

依赖倒置原则

抽象工厂模式通过依赖于抽象(接口或抽象类)而不是具体实现,从而减少了客户端与具体类的耦合。客户端与抽象工厂交互,而不是与具体工厂或具体产品直接交互。

接口隔离原则

虽然抽象工厂模式提供了一个创建相关对象的接口,但在设计时应谨慎考虑接口的职责,避免将不相关的创建方法放在同一个接口中,以符合接口隔离原则。

抽象工厂模式在设计时需要仔细考虑产品族的划分和工厂接口的设计,以确保系统的灵活性和可扩展性。在下一部分中,我们将探讨抽象工厂模式的使用场景。

第三部分:抽象工厂模式使用场景

3.1 产品族的多样化

何时产品族具有多样化特征

产品族指的是一组具有共同主题或共享通用接口的产品。当这些产品需要根据不同的场景或条件以不同的方式进行组合时,产品族就呈现出多样化特征。

  • 例子:考虑一个图形界面库,它可能包含多种形状(如圆形、矩形、三角形)和多种颜色(如红色、蓝色、绿色)。不同的应用程序可能需要不同的形状和颜色组合,例如,一个儿童绘画程序可能需要鲜艳的颜色和简单的形状。

适合使用抽象工厂模式的情况

  • 当存在多个产品族,并且每个产品族中的产品需要一起使用时。
  • 当需要提供产品族的不同变体,以适应不同的环境或条件时。

抽象工厂模式的应用

  • 通过定义一个抽象工厂接口,不同的具体工厂可以实现这个接口,以创建特定产品族中的对象。
  • 客户端代码通过抽象工厂接口与具体工厂交互,请求所需的产品族,而无需关心具体的产品实现。

3.2 系统之间的依赖关系

系统间依赖关系的问题

在大型软件系统中,不同的组件或模块之间可能存在依赖关系。如果这些依赖关系处理不当,可能会导致代码难以维护和扩展。

抽象工厂模式如何进行有效管理

  • 解耦:抽象工厂模式通过将对象创建的逻辑集中到具体的工厂类中,降低了模块间的直接依赖。
  • 配置化:系统可以通过配置或参数化的方式,动态选择使用哪个具体工厂,从而适应不同的运行时条件。

应用实例

  • 主题定制:在一个支持主题定制的应用程序中,可以为不同的主题定义不同的工厂,每个工厂负责创建符合该主题的视觉元素。
  • 数据库连接:在需要连接多种数据库系统的应用程序中,可以为每种数据库类型定义一个具体的工厂,而客户端则通过抽象工厂接口请求数据库连接。

通过抽象工厂模式,可以在不同的系统或组件之间建立一个清晰且灵活的接口,使得它们能够更容易地协同工作,同时保持各自的独立性和可扩展性。在下一部分中,我们将讨论抽象工厂模式的优点与缺点。

第三部分:抽象工厂模式使用场景

3.1 产品族的多样化

在软件开发中,产品族指的是一组具有共同接口但实现不同的类。当这些类需要根据不同的情境或配置以不同的方式进行组合时,就表现为产品族的多样化。

何时产品族具有多样化特征:

  • 当存在多个产品系列,每个系列都有多种产品变体时。
  • 当产品之间存在依赖关系,需要一起使用以保证一致性时。

适合使用抽象工厂模式的情况:

  • 当需要创建的产品族具有多种变体,且这些变体在结构上相关联时。
  • 当系统需要支持多种主题或外观,例如不同的GUI主题。

3.2 系统之间的依赖关系

系统间的依赖关系管理是软件设计中的一个关键问题。抽象工厂模式通过将创建逻辑封装在工厂类中,有助于降低系统间的耦合度。

系统间依赖关系的问题:

  • 当一个系统组件直接依赖于另一个组件的具体实现时,会导致组件之间的耦合度过高。

抽象工厂模式如何进行有效管理:

  • 通过定义一个抽象工厂接口,不同的系统可以提供各自的具体工厂实现,从而生产出符合各自需求的产品。
  • 客户端代码通过抽象工厂接口与具体工厂解耦,可以灵活地替换具体的工厂实现,以适应不同的业务需求。

第四部分:抽象工厂模式的优点与缺点

4.1 优点

灵活性和可扩展性:

  • 抽象工厂模式允许系统在不修改现有代码的基础上引入新的产品族,提高了系统的可扩展性。

解耦:

  • 客户端代码与具体工厂实现解耦,降低了模块间的依赖。

一致性:

  • 确保了产品族中的对象是一起创建的,从而保证了对象之间的一致性。

4.2 缺点

系统复杂度增加:

  • 每增加一个新的产品族,都需要增加一个新的具体工厂类和产品类,可能会导致系统中类的数量急剧增加。

难以维护:

  • 随着产品族的增加,抽象工厂模式可能会导致系统结构变得更加复杂,难以理解和维护。

不够灵活:

  • 如果系统需要支持多种产品族的任意组合,抽象工厂模式可能不如其他模式(如建造者模式)灵活。

在实际应用中,选择抽象工厂模式需要权衡其优点和缺点。如果系统中存在多个产品族,并且这些产品族需要一起使用,抽象工厂模式是一个不错的选择。然而,如果系统需要高度的灵活性和扩展性,可能需要考虑其他设计模式。在下一部分中,我们将比较抽象工厂模式与其他设计模式,并提供一些最佳实践和建议。

第五部分:抽象工厂模式与其他模式的比较

5.1 与工厂方法模式的比较

工厂方法模式

  • 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
  • 使用场景:当需要创建的对象类型相对较少,且这些对象的创建逻辑可以封装在一个共同的工厂类中。

抽象工厂模式

  • 定义:提供一个创建一系列相关或相互依赖对象的接口,而不需要具体指定它们的类。
  • 使用场景:当存在多个产品族,且这些产品族需要一起使用时。

不同点

  • 产品种类:工厂方法模式通常用于创建单一对象,而抽象工厂模式用于创建相关对象的族。
  • 扩展性:抽象工厂模式在添加新的产品族时更加灵活,而工厂方法模式更适合对象创建逻辑相对固定的情况。

5.2 与建造者模式的对比

建造者模式

  • 定义:用于创建一个复杂的对象,同时允许用户只通过指定复杂对象的类型和内容就能构建它们。
  • 使用场景:当对象的创建过程涉及多个步骤,或者对象的创建逻辑较为复杂时。

抽象工厂模式

  • 定义:用于创建一系列相关或相互依赖的对象。
  • 使用场景:当需要同时创建多个相关对象,并且这些对象的创建逻辑可以封装在一个共同的工厂类中。

不同点

  • 复杂性:建造者模式适用于构建过程复杂或步骤繁多的对象,而抽象工厂模式适用于创建对象族。
  • 灵活性:建造者模式在构建过程中提供了更多的控制和灵活性,而抽象工厂模式则强调了对象族的一致性。

第六部分:最佳实践和建议

6.1 使用抽象工厂模式的最佳时机

  • 产品族多样化:当系统中存在多个产品族,且这些产品族需要根据不同的配置或条件进行变化时。
  • 系统解耦:当需要降低系统组件之间的耦合度,提高模块的独立性和可替换性时。

6.2 避免滥用抽象工厂模式

  • 过度扩展:避免在产品族非常简单或不相关的情况下使用抽象工厂模式,这可能会导致不必要的系统复杂性。
  • 难以维护:随着产品族的增加,管理大量的工厂类和产品类可能会变得困难。

6.3 替代方案

原型模式

  • 定义:通过复制现有的对象来创建新的实例。
  • 适用场景:当创建新对象的成本较高,或者需要快速复制现有对象时。

依赖注入

  • 定义:通过外部提供依赖对象,而不是在类内部创建。
  • 好处:提高了代码的可测试性和灵活性。

服务定位器模式

  • 定义:用于查找和访问服务的机制。
  • 适用场景:当系统中有大量的服务需要被访问,并且服务实例的创建和管理较为复杂时。

抽象工厂模式是一种强大的设计模式,适用于创建相关或依赖对象族的场景。然而,合理选择使用时机和避免滥用同样重要。了解替代方案可以帮助开发者根据具体需求选择最合适的设计模式。

结语

抽象工厂模式是处理复杂系统中对象创建问题的有效工具。通过本文的深入分析,希望读者能够对抽象工厂模式有更全面的理解,并在实际开发中做出合理的设计选择。

 

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

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

相关文章

Redis Cluster集群搭建只能正常启动一个怎么解决

Redis Cluster集群搭建只能正常启动一个怎么解决 建立redis集群时不小心就遇到了这问题 上图看 这两个都没有问题 接下来这个就出现问题啦 6380没有cluster集群 这个就是连不上 配置文件没错 看了几遍了 那该怎么办? 明明都一样的配置文件,为啥这…

成都亚恒丰创教育科技有限公司 【插画猴子:笔尖下的灵动世界】

在浩瀚的艺术海洋中,每一种创作形式都是人类情感与想象力的独特表达。而插画,作为这一广阔领域中的璀璨明珠,以其独特的视觉语言和丰富的叙事能力,构建了一个又一个令人遐想连篇的梦幻空间。成都亚恒丰创教育科技有限公司 在众多插…

解析DDD中的聚合对象

对象这个词对我们而言并不陌生。以最常见的面向对象为例,软件系统中的任何事物都被认为是一种对象。而针对如何设计和实现这些对象,也存在一批开发模式。例如,一种传统的做法是从数据的角度来规划对象的组织形式,先设计数据库模型…

甲骨文面试题【动态规划】力扣377.组合总和IV

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 示例 1: 输入:nums [1,2,3], target 4 输出:7 解释&#x…

QTableView仿Excel表头排序和筛选

一.效果 Excel的排序和筛选弹窗如下所示 功能非常强大。不仅支持内容排序和筛选,还支持颜色的排序和筛选,而且还支持设置多种过滤条件。本文只仿最常用的内容排序和内容单过滤条件的筛选,效果如下所示。 从效果图中可以看出,表头Section中的按钮有下列六种状态 enum Butt…

Redis 教程:从入门到入坑

目录 1. Redis 安装与启动1.1. 安装 Redis1.1.1. 在Linux上安装1.1.2. 在Windows上安装 1.2. 启动 Redis1.2.1. 在Linux上启动1.2.2. 在Windows上启动 1.3. 连接Redis1.3.1. 连接本地Redis1.3.2. 连接远程Redis1.3.2.1. 服务器开放端口1.3.2.2. 关闭防火墙1.3.2.3. 修改配置文件…

GESP CCF C++ 三级认证真题 2024年6月

第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有()种。 A. 1 B. 2 C. 3 D. 4 第 2 题 下面流程图在yr输入2024时,可以判定yr代表闰年,并输出 2月是29天 &#x…

【整体介绍】HTML和JS编写多用户VR应用程序的框架

一、Networked-Aframe是什么? 简称NAF,底层基于Mozilla的AFrame框架,用HTML和JS编写多用户VR应用程序的框架。 二、特性 支持 WebRTC 和/或 WebSocket 连接。 语音聊天。音频流让您的用户在应用程序内交谈(仅限 WebRTC&#xff…

AV1技术学习: Compound Prediction

一、双向 Compound Prediction AV1支持两个参考帧的预测通过多种复合模式线性组合。复合预测公式为 其中,权重m(x, y) is scaled by 64 以进行整数计算,R1(x, y)和R2(x, y)表示两个参考块中位于(x, y)的像素。P(x, y)将按比例缩小 1/64 以形成最终的预测…

Android安卓使用MQTT(JAVA)

一、app目录下添加 implementation org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0 1) 点击Sync Now更新依赖 2) AndroidManifest.xml文件添加网络权限 <uses-permission android:name"android.permission.INTERNET"/> 二、 使用 1) 创建MqttConn…

使用 ABBYY FineReader PDF 15 在创建或转换 PDF 时自动生成书签

使用 ABBYY 为 PDF 文件添加书签&#xff0c;可以帮助快速定位文档中的主要内容&#xff0c;也能更方便的梳理出一份文档大纲。 有很多 PDF 文件在创建时并没有编辑书签&#xff0c;这里介绍使用 ABBYY FineReader PDF 15&#xff08;Win 系统&#xff09;在 PDF 中自动添加书…

postMessageXss续2

原文地址如下:https://research.securitum.com/art-of-bug-bounty-a-way-from-js-file-analysis-to-xss/ 在19年我写了一篇文章&#xff0c;是基于postMessageXss漏洞的入门教学:https://www.cnblogs.com/piaomiaohongchen/p/14727871.html 这几天浏览mXss技术的时候&#xff…

第三周周三总结

1.给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 1&#xff1a; 输…

RuoYi-后端管理项目入门篇1

目录 前提准备 下载若依前后端 Gitee 地址 准备环境 后端数据库导入 1 克隆完成 若依后端管理后端 Gitte 地址 :若依/RuoYi-Vue 2.1 创建Data Source数据源 2.2 填写好对应的数据库User 和 Password 点击Apply 2.3 新建一个Schema 2.4 填写对应数据库名称 这边演示写的…

【I²C协议】STC89C51单片机IIC通信(代码+原理)

STC89C51单片机IIC通信 什么是IC协议特点构成 通信协议开始信号、结束信号、应答信号数据传输 代码示例 什么是IC协议 IIC,即IC&#xff0c;全称 Inter-Integrated Circuit&#xff0c;字面上的意思是集成电路之间&#xff0c;它其实是IC Bus简称&#xff0c;所以中文应该叫 集…

【Codeforces】Round 957 (Div. 3)_B. Angry Monk

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法刷题 &#x1f43e;或许会很慢&#xff0c;但是不可以停下来&#x1f43e; 文章目录 题目题解try1代码正确题解贪心策略的解释为什么不是直接合并 总结 题目 题目链接 题解 try1代码 我的思路&#xff1a;单纯模拟 循环&a…

【字幕】字幕特效入门

前言 最近两周调研了一下字幕特效的底层程序逻辑&#xff0c;因为工作内容的原因&#xff0c;就分享几个自己找的链接具体细节就不分享了&#xff0c;CSDN也是我的个人笔记&#xff0c;只记录一些简单的内容用于后续自己方便查询&#xff0c;顺便帮助一下正在苦苦查阅资料入门…

基于STC89C51单片机的烟雾报警器设计(煤气火灾检测报警)(含文档、源码与proteus仿真,以及系统详细介绍)

本篇文章论述的是基于STC89C51单片机的烟雾报警器设计的详情介绍&#xff0c;如果对您有帮助的话&#xff0c;还请关注一下哦&#xff0c;如果有资源方面的需要可以联系我。 目录 摘要 原理图 实物图 仿真图 元件清单 代码 系统论文 资源下载 摘要 随着现代家庭用火、…

【高中数学/指数函数、幂函数】寻找曲线y=2^x与y=x^2的三个交汇点

【问题】 找到曲线y2^x与yx^2的三个交汇点。 【难点】 指数和二次函数摆在一起没法求解。 【解答】 y2^x与yx^2的交汇点&#xff0c;即曲线y2^x-x^2的零点&#xff0c;用Canvas作图就能清晰看到三个零点的存在&#xff0c;如图。 【图一】 其中&#xff0c;2&#xff0c;…

自制连点器

B站使用教程&#xff1a;https://www.bilibili.com/video/BV1SR85e4EKw/?vd_source47eba1800d831e86d4778a128740fe73 下载链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1Spv_yVPFB3zoS__VL-nhaQ?pwdyxo1 提取码&#xff1a;yxo1