[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式

前言:
为什么之前写过Golang 版的设计模式,还在重新写Java 版?
答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。
为什么类图要附上uml
因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那么学习者也只能复制一张图片,可复用性较低,附上uml,方便有新理解时,快速出新图。


🔥[设计模式Java实现附plantuml源码]专链

  1. 确保对象的唯一性~单例模式
  2. 集中式工厂的实现~简单工厂模式
  3. 多态工厂的实现——工厂方法模式
  4. 产品族的创建——抽象工厂模式

文章目录

      • 代码实现
      • 抽象工厂总结
        • 抽象工厂模式的主要优点如下:
        • 抽象工厂模式的主要缺点是:
      • 适用场景


工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题。但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产,这就是本章将要学习的抽象工厂模式的基本思想。

为了更好地理解抽象工厂模式,这里先引入如下两个概念:
(1)产品等级结构。产品等级结构即产品的继承结构,例如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
(2)产品族。在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。例如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。
image.png

抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。
抽象工厂模式定义如下:抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。

在这里插入图片描述

@startumlabstract class 抽象产品族1海尔{}class 产品1电视机 extends 抽象产品族1海尔 {}
class 产品2洗衣机 extends 抽象产品族1海尔 {}abstract class 抽象产品族2{}abstract class 抽象工厂 {+ 生产抽象产品族1():抽象产品族1海尔
+ 生产抽象产品族2():抽象产品族2
}class 具体工厂1 extends 抽象产品族1海尔 implements 抽象工厂 {
+ 生产产品1():抽象产品族1海尔
+ 生产产品2():抽象产品族1海尔
}具体工厂1 -up-> 产品1电视机
具体工厂1 -up-> 产品2洗衣机@enduml

在抽象工厂模式结构图中包含以下4个角色。
(1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每个方法对应一种产品。
(2)ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每种产品都位于某个产品等级结构中。
(3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
(4)ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现在抽象产品接口中声明的业务方法。

代码实现

public class AbstractFactoryDemo {// 抽象产品族1static abstract class AbstractProductFamily1 {}// 产品1static class Product1 extends AbstractProductFamily1 {}// 产品2static class Product2 extends AbstractProductFamily1 {}// 抽象产品族2static abstract class AbstractProductFamily2 {}// 抽象工厂interface AbstractFactory {AbstractProductFamily1 createProductFamily1();AbstractProductFamily2 createProductFamily2();}// 具体工厂1static class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductFamily1 createProductFamily1() {return new Product1();}@Overridepublic AbstractProductFamily2 createProductFamily2() {// 在具体工厂1中创建抽象产品族2的实例return null; // 根据具体情况进行实现}}public static void main(String[] args) {// 创建具体工厂1的实例AbstractFactory factory = new ConcreteFactory1();// 使用具体工厂1创建抽象产品族1的实例AbstractProductFamily1 product1 = factory.createProductFamily1();AbstractProductFamily1 product2 = factory.createProductFamily1();System.out.println(product1);System.out.println(product2);// 使用具体工厂1创建抽象产品族2的实例AbstractProductFamily2 product3 = factory.createProductFamily2();System.out.println(product3);}}

抽象工厂总结

抽象工厂模式的主要优点如下:

(1)抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了在抽象工厂中声明的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
(2)当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
(3)增加新的产品族很方便,无须修改已有系统,符合开闭原则。

抽象工厂模式的主要缺点是:

增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则。

适用场景

在以下情况下可以考虑使用抽象工厂模式:
(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。
(2)系统中有多于一个的产品族,而每次只使用其中某一个产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。
(3)属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束。例如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类 型。
(4)产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。

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

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

相关文章

基于web的亚热带常见自然林病虫害识别系统——数据集与数据集划分

文章目录 概要数据收集数据集划分技术代码小结 概要 本篇文章先为病虫害识别进行数据的分类,划分训练集,划分为三个数据集,病虫害的数据集我已经放在我的资源里面,有需要的小伙伴可以自己下载。 声明: 我的数据集照片…

【nowcoder】链表的回文结构

牛客题目链接 链表的回文结构 /* struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {} };*/ #include <cstdlib> // 建议大伙自己对照我的代码画下图&#xff0c;假设A链表是&#xff1a;1 2 3 2 1 class PalindromeList { publi…

JavaScript进阶:WebAPIs重点知识整理3

1 本地存储 存储容量大&#xff1a;约5M 1.1 localStorage 1.1.1 存储 localStorage.setItem(username,张三) localStorage.setItem(password,123456) 1.1.2 获取 console.log(localStorage.getItem(username)) 1.1.3 删除 localStorage.removeItem(username) 1.2 session…

【业务功能篇133】 Mysql连接串优化性能问题

rewriteBatchedStatementstrue开启了MySQL驱动程序的批量处理功能。 spring.datasource.urljdbc:mysql://localhost:3306/mydatabase?rewriteBatchedStatementstrue 在MyBatis Plus框架中&#xff0c;批量插入是一种高效的数据库操作方式。通过开启rewriteBatchedStatementstr…

栈实现队列(附带源码)

一、思路图解 首先&#xff0c;队列&#xff1a;先进先出 栈&#xff1a;先进后出 那么&#xff0c;怎么用栈实现队列呢&#xff1f; 很简单&#xff0c;首先&#xff0c;创建两个栈 一个叫pushsatck,用来入队列 一个叫popstack,用来出队列 队列的核心在于先进先出&#xf…

2024.1.24 C++QT 作业

思维导图 练习题 1.提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 #include <iostream> #include <string.h> #include <array> using namespace std;int main() {string str;cout << "…

Linux shell编程学习笔记41:lsblk命令

边缘计算的挑战和机遇 边缘计算面临着数据安全与隐私保护、网络稳定性等挑战&#xff0c;但同时也带来了更强的实时性和本地处理能力&#xff0c;为企业降低了成本和压力&#xff0c;提高了数据处理效率。因此&#xff0c;边缘计算既带来了挑战也带来了机遇&#xff0c;需要我…

【Java】Java JSR303应用解决数据校验问题,解放双手

文章目录 JSR303Hibernate 对其实现应用进阶-注解分组使用首先声明两个空接口为实体类上的注解添加接口标记controller具体的接口方法添加分组标记 异常类搭配使用说明&#xff1a; JSR303 JSR是Java Specification Requests的缩写&#xff0c;意思是Java 规范提案。是指向JCP…

线性表--链表--带头双向循环链表

目录 1.什么是带头双向循环链表&#xff1f; 2.实现增删查改功能&#xff1a; 2.1使用链表前必须对头节点初始化 2.2尾插 2.3尾删 2.4头插 2.5头删 2.8查找 2.7指定位置插入 2.8指定位置删除 2.9改变数据 ​编辑 2.10打印 2.11销毁 3.代码 1.什么是带头双向循环链表&…

openGauss学习笔记-206 openGauss 数据库运维-常见故障定位案例-too many clients already

文章目录 openGauss学习笔记-206 openGauss 数据库运维-常见故障定位案例-too many clients already206.1 高并发报错“too many clients already”或无法创建线程206.1.1 问题现象206.1.2 原因分析206.1.3 处理办法 openGauss学习笔记-206 openGauss 数据库运维-常见故障定位案…

安卓移动设备使用DS file文件管理工具远程访问本地群晖NAS文件

文章目录 1. 群晖安装Cpolar2. 创建TCP公网地址3. 远程访问群晖文件4. 固定TCP公网地址5. 固定TCP地址连接6. 结语 DS file 是一个由群晖公司开发的文件管理应用程序&#xff0c;主要用于浏览、访问和管理存储在群晖NAS&#xff08;网络附加存储&#xff09;中的文件。这个应用…

C++基础学习

在我们学习类之前我们先学习下其他几个相关的知识点. 一.内联函数 定义&#xff1a; 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率 如果你想去查看&…