「聊设计模式」之抽象工厂模式(Abstract Factory)


🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!


前言

  在软件开发中,设计模式是一种被广泛使用的经验总结,它们为我们提供了一套已经经过验证的,可以复用的解决方案,可以帮助开发人员有效地解决常见问题,提高软件质量和可维护性。

  本文将介绍抽象工厂模式(Abstract Factory),这是一种创建型设计模式,它提供了一种创建与一组相关对象的方式,而无需指定其具体类。本文将详细介绍抽象工厂模式的概念、实现方法以及测试用例,并展示它在Java中的实现。

摘要

  抽象工厂模式是一种通过接口或抽象类来创建一系列相关或依赖对象的设计模式。它是工厂方法模式的扩展,它可以创建多个产品族,而工厂方法模式只能创建单个产品族。抽象工厂模式通过将工厂的抽象与产品的抽象相匹配来实现这一目标。

抽象工厂模式

概念

  抽象工厂模式是一种创建型设计模式,它提供了创建一组相关或依赖对象的接口,无需指定它们具体的类。它通过将工厂的抽象与产品的抽象相匹配来实现这一目标。

  抽象工厂模式是在工厂方法模式的基础上发展而来的。工厂方法模式只能创建单个产品族,而抽象工厂模式可以创建多个产品族。在抽象工厂模式中,每个工厂类只负责创建对应产品族的产品,在工厂内部,通过抽象产品的公共接口来实现不同产品族的产品创建。

实现方法

如下我给大家用代码亲自演示一下抽象工厂模式,具体请看如下代码:

1. 创建抽象工厂类

  抽象工厂类中需要定义用于创建产品族的抽象方法,抽象方法返回抽象产品。在Java中,可以使用抽象类或接口来定义抽象工厂。

package com.example.javaDesignPattern.abstractFactory;/*** 抽象工厂类** @author bug菌* @version 1.0* @date 2023/9/18 17:29*/
public abstract class AbstractFactory {public abstract ProductA createProductA();public abstract ProductB createProductB();
}

2. 创建具体工厂类

  具体工厂类实现抽象工厂类中定义的抽象方法,用于创建具体的产品。具体工厂类中也可以包含额外的方法和属性,用于定制化产品的创建。

如下创建第一个具体工厂类,示例代码如下:

package com.example.javaDesignPattern.abstractFactory;/*** 创建具体工厂类** @author bug菌* @version 1.0* @date 2023/9/18 17:30*/
public class ConcreteFactory1 extends AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}

如下接着创建第二个具体工厂类,示例代码如下:

package com.example.javaDesignPattern.abstractFactory;/*** 创建具体工厂类** @author bug菌* @version 1.0* @date 2023/9/18 17:30*/
public class ConcreteFactory2 extends AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic ProductB createProductB() {return new ConcreteProductB2();}
}

3. 创建抽象产品类

  抽象产品类定义产品的公共接口,从而使不同具体产品类可以实现相同的接口。

public abstract class ProductA {public abstract void display();
}
public abstract class ProductB {public abstract void show();
}

  以上代码是创建抽象类的示例。抽象类是不能被实例化的类,只能被继承,因此抽象类通常用于作为其他类的基类。在以上代码中,ProductA和ProductB都是抽象类。

  在ProductA类中,定义了一个抽象方法display(),该方法没有具体的实现,只有方法签名。所有继承自ProductA的子类在实现该方法时,需要给出具体的实现。由于抽象类不能被实例化,因此使用抽象方法可以让子类在具体实现时覆盖基类的实现,实现多态性。

  在ProductB类中,同样定义了一个抽象方法show()。和ProductA类中的display()方法类似,子类需要实现show()方法以满足多态性的需求。

  需要注意的是,抽象类中可以包含非抽象方法和属性,在子类继承后可以直接使用,不需要覆盖实现。

4. 创建具体产品类

  具体产品类实现抽象产品类中定义的抽象方法,用于实例化具体的产品。

public class ConcreteProductA1 extends ProductA {@Overridepublic void display() {System.out.println("ConcreteProductA1 display");}
}
public class ConcreteProductB1 extends ProductB {@Overridepublic void show() {System.out.println("ConcreteProductB1 show");}
}
public class ConcreteProductA2 extends ProductA {@Overridepublic void display() {System.out.println("ConcreteProductA2 display");}
}

public class ConcreteProductB2 extends ProductB {@Overridepublic void show() {System.out.println("ConcreteProductB2 show");}
}

  在如上代码,ConcreteProductA1ConcreteProductA2继承了抽象产品类ProductA,分别实现了抽象产品类中的display()方法;ConcreteProductB1ConcreteProductB2继承了抽象产品类ProductB,分别实现了抽象产品类中的show()方法。这些具体产品类将被工厂类使用来创建具体产品对象。

5. 创建客户端代码

  客户端代码使用抽象工厂来获取其需要使用的产品,客户端代码不需要知道如何创建产品,只需要知道如何使用它们。

package com.example.javaDesignPattern.abstractFactory;/*** 创建客户端** @author bug菌* @version 1.0* @date 2023/9/18 17:33*/
public class Client {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();productA1.display();productB1.show();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.display();productB2.show();}
}

  客户端展示了抽象工厂模式的使用。客户端通过创建具体工厂对象(ConcreteFactory1ConcreteFactory2)来获得不同种类的产品对象(ProductAProductB)。客户端并不直接使用产品对象,而是通过工厂对象创建产品对象并调用它们的方法(display()show())。这样可以封装产品对象的创建过程,使得客户端只需要关注工厂对象和产品对象的接口,而不需要了解具体实现细节。

启动客户端测试结果如下:

在这里插入图片描述

【代码方法解读】

  其中,抽象工厂 AbstractFactory 定义了两个抽象方法 createProductA() createProductB(),分别用于创建产品 A 和产品 B。具体的工厂类ConcreteFactory1ConcreteFactory2 分别实现了这两个方法,并且分别用于创建不同的产品。

  在 Client 类的 main() 方法中,首先分别创建了 ConcreteFactory1ConcreteFactory2 两个工厂的实例。接着,通过这两个工厂实例的 createProductA()createProductB() 方法创建了不同的产品对象,并分别调用了它们的 display()show() 方法。

  因此,抽象工厂模式的主要优点是能够提供一致的产品族创建接口,使得客户端可以方便地创建一组相关的产品。同时也能遵循开闭原则,使得增加新的产品族比较容易,但同时也增加了类的数量,降低了系统的灵活性和可扩展性。

附录源码

  如上涉及代码均已上传同步在GitHub,提供给同学们参考性学习。

总结

  本文着重介绍了抽象工厂模式,该模式是创建型设计模式的一种,它提供了一种创建一组相关或依赖对象的方式,无需指定其具体类。抽象工厂模式是工厂方法模式的扩展,可以创建多个产品族,而工厂方法模式只能创建单个产品族。

  为了实现抽象工厂模式,需要先创建抽象工厂类,其中定义用于创建产品族的抽象方法,抽象方法返回抽象产品。具体工厂类实现抽象工厂类中定义的抽象方法,用于创建具体的产品。抽象产品类定义产品的公共接口,具体产品类实现抽象产品类中定义的抽象方法,用于实例化具体的产品。

  在客户端代码中,使用抽象工厂来获取需要使用的产品,不需要知道如何创建产品,只需要知道如何使用它们。

  抽象工厂模式可以帮助开发人员有效地解决常见问题,提高软件质量和可维护性,是软件开发中经常使用的一种设计模式。

☀️建议/推荐你


  如果想系统性的全面学习设计模式,建议小伙伴们直接毫无顾忌的关注这个专栏《聊设计模式》,无论你是想提升自己的编程技术,还是渴望更好地理解代码背后的设计思想,本专栏都会为你提供实用的知识和启发,帮助你更好地解决日常开发中的挑战,将代码变得更加优雅、灵活和可维护!

📣关于我


我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。

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

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

相关文章

C++(day4)

思维导图 封装Mystring #include <iostream> #include<cstring>using namespace std;class Mystring{ public://无参构造函数Mystring():size(10){strnew char[size];strcpy(str,"");cout<<"无参构造函数"<<endl;}//有参构造函数…

平衡二叉树删除结点后的调整操作

1.回顾插入操作 插入新结点后&#xff0c;要保持二叉排序树的特性不变&#xff08;左<中<右)若插入新结点导致不平衡&#xff0c;则需要调整平衡。 2.删除操作 删除结点后&#xff0c;要保持二叉排序树的特性不变&#xff08;左<中<右)若删除结点导致不平衡&…

MySQL只同步单个表或多个表,非全部同步!

replicate-do-table 是 MySQL 复制配置中的一个选项&#xff0c;它允许您指定要在从服务器上复制的表。如果您想要只复制主服务器上特定的表到从服务器&#xff0c;您可以使用这个选项。 以下是如何操作 replicate-do-table 的步骤&#xff1a; 停止从服务器: 在从服务器上执行…

C++---链表

1、链表 1.1、链表的结构 每个链表开头都有一个头指针Head尾节点的指针域为NULL&#xff0c;用于判断此列表是否结束 如果一个链表开始就为NULL&#xff0c;那么该链表为空链表 链表中的先后不代表在真实内存中的位置&#xff0c;只是单纯的逻辑上关系 1.2、创建链表 我们首…

网络编程 day1

1->x.mind网络编程基础 2->简述字节序的概念&#xff0c;并用共用体&#xff08;联合体&#xff09;的方式计算本机的字节序 1.字节序是指不同类型的CPU主机&#xff0c;内存存储多字节整数序列的方式 2.小端字节序&#xff1a;低序字节存储在低地址上 3.大端字节序&a…

day19正则表达式

今日内容 正则表达式 教学目标 能够理解正则表达式的作用 能够使用正则表达式的字符类 能够使用正则表达式的逻辑运算符 能够使用正则表达式的预定义字符类 能够使用正则表达式的限定符 能够使用正则表达式的分组 能够在String的split方法中使用正则表达式 正则表达式 1.1 …

C++:constexpr 和 const 的区别

constexpr 是 C 11 标准新添加的关键字&#xff0c;原先的标准中是只有const关键字的&#xff0c;作用是表示只读常量。但是&#xff0c;其实只读常量是两个属性&#xff0c;分为只读和常量&#xff0c;都用const来表示会产生歧义。 看下面的例子 #include <iostream> …

Layui + Flask | 弹出层(组件篇)(04)

提示:点击阅读原文体验更佳 https://layui.dev/docs/2.8/layer/ 弹出层组件 layer 是 Layui 最古老的组件,也是使用覆盖面最广泛的代表性组件。在实现网页弹出层的首选交互方案,使用的非常频繁。 打开弹层 layer.open(options); 参数 options : 基础属性配置项。打开弹层的核…

定制化图标——Element UI 组件图标替换指南

本篇博客将介绍如何在使用 Element UI 组件时对原生图标进行定制化替换&#xff0c;提供了适用于满足个性化需求的方法和技巧。 引言 Element UI 是一款基于 Vue.js 的流行 UI 组件库&#xff0c;在前端开发中得到广泛应用。然而&#xff0c;在使用 Element UI 的组件时&#…

中小型教育机构这样做,让你轻松抓住受众注意力

教育一直都是家长对于孩子最关心的事情&#xff0c;对于部分家庭来说&#xff0c;教育支出占整个家庭支出的50%左右。 而软文作为目前效果比较明显而且性价高的推广方式&#xff0c;也很适合教育培训行业&#xff0c;因为它能让潜在客户可以清楚地了解产品的特性&#xff0c;感…

springcloude gateway的意义

应用场景 1、南北向流量 需要流量网关和微服务网关配合使用&#xff0c;将内部的微服务能力&#xff0c;以统一的 HTTP 接入点对外提供服务。 流量网管主要是接入流量进行负载均衡&#xff0c;上游的微服务网关地址和数量变化不大&#xff0c;对服务发现要求不高。 微服务网…

Java面试八股文宝典:初识数据结构-数组的应用扩展之HashMap

前言 除了基本的数组&#xff0c;还有其他高级的数据结构&#xff0c;用于更复杂的数据存储和检索需求。其中&#xff0c;HashMap 是 Java 集合框架中的一部分&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。HashMap 允许我们通过键来快速查找和检索值&…

004-Windows下开发环境搭建

Windows下开发环境搭建 文章目录 Windows下开发环境搭建项目介绍版本控制工具Git 与 SVNWindow下安装Git Qt 开发工具静态编译Qt环境安装 串口模拟器比较工具SQLite 数据库查看小工具预告 关键字&#xff1a; Qt、 Qml、 开发环境、 Windows、 C 项目介绍 欢迎来到我们的 …

数据库操作-DML/DQL

数据库操作-DML DML英文全称是Data Manipulation Language(数据操作语言)&#xff0c;用来对数据库中表的数据记录进行增、删、改操作。 添加数据&#xff08;INSERT&#xff09; 修改数据&#xff08;UPDATE&#xff09; 删除数据&#xff08;DELETE&#xff09; 增加(ins…

python 异常

1.捕获异常 2.密码爆破 3.

基于b/s架构搭建一个支持多路摄像头的实时处理系统 (3) -- Django 结合WebSocket 进行实时图像与消息的展示, 前后端交互与定时任务的重构

文章大纲 consumersself.scope参考文献与学习路径javascript html websocketpython 定时任务Django 实时通信后端 channelconsumers https://channels.readthedocs.io/en/stable/topics/consumers.htmlself.scope consumer在初始化时会接受链接的scope,类似于Django中的reque…

查看云桌面请求linux服务器网络快慢

要查看云桌面请求 Linux 服务器的网络快慢&#xff0c;您可以使用一些网络诊断工具和命令来评估连接的性能。以下是一些方法&#xff1a; 使用 ping 命令&#xff1a; ping 命令可以测试与目标服务器之间的网络连接。在终端中运行以下命令以测试服务器的响应时间&#xff1a; p…

【业务功能118】微服务-springcloud-springboot-Kubernetes集群-k8s集群-KubeSphere-OpenELB部署及应用

OpenELB部署及应用 一、OpenELB介绍 网址&#xff1a; openelb.io OpenELB 是一个开源的云原生负载均衡器实现&#xff0c;可以在基于裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。OpenELB 项目最初由 KubeSphere 社区发…

用Python把csv文件批量修改编码为UTF-8格式并转为Excel格式

有时候用excel打开一个csv文件&#xff0c;中文全部显示乱码。然后手动用notepad打开&#xff0c;修改编码为utf-8并保存后&#xff0c;再用excel打开显示正常。 使用Python通过很少代码就能将上面过程自动化。 导入3个模块 import pandas as pd import os import chardetc…

Python 3 – 文件 readline() 方法

Python 3 – 文件 readline() 方法|极客笔记 # 打开文件 file open("example.txt", "r")# 读取文件中的一行数据 line file.readline() while line:# 移除行尾的换行符print(line.strip())# 读取文件中的下一行数据line file.readline()# 关闭文件 file…