设计模式篇---抽象工厂(包含优化)
文章目录
- 概念
- 结构
- 实例
- 优化
概念
抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
工厂方法是有一个类型的产品,也就是只有一个产品的抽象类或接口,而抽象工厂相对于工厂方法来说,是有n个类型的产品,也就具有n个产品的抽象类或接口。通俗的来讲,就是由生成一个类型的产品转变为生成一组产品,这是二者的主要区别,两个的相同点是抽象的工厂接口里关联的永远是抽象的产品。
结构
抽象工厂的类图如下:

AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品(抽象的产品)。
ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品。
AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
实例
现在有海尔和海信两家公司,都会生产电视和空调,根据这种场景,我们可以拆分一下,把电视和空调作为产品族,海尔和海信两家公司作为两个生产产品的抽象工厂,它们都可以生产电视和空调。
空调的抽象产品:
public interface HVAC {void displayHVAC();
}
海尔空调:
public class HaierHVAC implements HVAC {@Overridepublic void displayHVAC() {System.out.println("海尔空调");}
}
海信空调:
public class HisenseHAVC implements HVAC{@Overridepublic void displayHVAC() {System.out.println("海信空调");}
}
电视的抽象产品:
public interface TV {void displayTV();
}
海尔电视:
public class HaierTV implements TV{@Overridepublic void displayTV() {System.out.println("海尔电视");}
}
海信电视:
public class HisenseHAVC implements HVAC{@Overridepublic void displayHVAC() {System.out.println("海信空调");}
}
抽象的工厂,海信工厂和海尔工厂实现该接口:
public interface AbstractFactory {TV createTV();HVAC createHVAC();
}
海尔工厂:
public class HaierFactory implements AbstractFactory{@Overridepublic TV createTV() {return new HaierTV();}@Overridepublic HVAC createHVAC() {return new HaierHVAC();}
}
海信工厂:
public class HisenseFactory implements AbstractFactory {@Overridepublic TV createTV() {return new HisenseTV();}@Overridepublic HVAC createHVAC() {return new HisenseHAVC();}
}
客户端实现:
public class Client {public static void main(String[] args) {//创建海尔的空调和电视AbstractFactory haierFactory = new HaierFactory();TV haierTV = haierFactory.createTV();HVAC haierHVAC = haierFactory.createHVAC();haierTV.displayTV();haierHVAC.displayHVAC();}
}
结果:

优化
抽象工厂比工厂方法多了一个产品族的抽象,也就是可以在工厂里创建多个产品。当新的公司介入时,如长虹公司也来了,那就在实现一个长虹公司的工厂,实现抽象工厂,然后重写里面的方法即可。
但是假如海尔和海信不仅仅生产空调和电视了,还想生产冰箱,那就需要再增加一个产品,这时,海尔和海信工厂都需要增加一个生产冰箱的方法,假如有n个像海尔和海信这样的工厂,那每个工厂都需要重写方法,很难扩展。
于是我苦思冥想,终于想到了一个方案,先说下思路:
1、因为当扩展新的产品时,就要重写工厂的方法,所以这个工厂里,我打算只放一个获取产品的方法,返回类型是一个抽象的产品。
2、要实现完全的开闭原则不太现实,只能减少对原有类的影响,要改的话只改动一个类就好,所以可以把需要变动的地方都放到一个类中,需要变动的点就是扩展新的产品。
3、因为客户面向的是抽象,所以在客户端不能出现具体的产品,只能出现抽象产品,但是可以通过字符串的形式进行传参,这样与每个类都没有耦合。
4、因为海尔和海信的工厂是固定的,可以在里面出现魔法值。
下面是优化的效果:
抽象工厂类,只有一个抽象的方法:
public interface AbstractFactory {Product create(String type);
}
海尔工厂类,可通过反射获取具体的产品:
public class HaierFactory implements AbstractFactory {@Overridepublic Product create(String type) {Map<String, String> productClassNameByType = ExtendUtil.getProductClassNameByType(type);String className = productClassNameByType.get("haier");Object o = null;try {o = Class.forName(className).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return (Product) o;}
}
海信工厂类:
public class HisenseFactory implements AbstractFactory {@Overridepublic Product create(String type) {Map<String, String> productClassNameByType = ExtendUtil.getProductClassNameByType(type);String className = productClassNameByType.get("hisense");Object o = null;try {o = Class.forName(className).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return (Product) o;}
}
一个工具类,用来扩展使用,存放产品族和具体产品之间的关系:
public class ExtendUtil {private static Map<String, Map<String, String>> map = new HashMap<>();static {map = new HashMap<String, Map<String, String>>() {{Map<String, String> tvMap = new HashMap<>();tvMap.put("haier", "com.tfjybj.ming.design.absfactory.HaierTV");tvMap.put("hisense", "com.tfjybj.ming.design.absfactory.HisenseTV");put("tv", tvMap);Map<String, String> hvacMap = new HashMap<>();hvacMap.put("haier", "com.tfjybj.ming.design.absfactory.HaierHVAC");hvacMap.put("hisense", "com.tfjybj.ming.design.absfactory.HisenseHVAC");put("hvac", hvacMap);}};}public static Map<String,String> getProductClassNameByType(String type){return map.get(type);}
}
最抽象的产品:
public interface Product {void display();
}
海尔电视:
public class HaierTV implements Product {@Overridepublic void display() {System.out.println("海尔电视");}
}
海尔空调:
public class HaierHVAC implements Product {@Overridepublic void display() {System.out.println("海尔空调");}
}
海信电视:
public class HisenseTV implements Product {@Overridepublic void display() {System.out.println("海信电视");}
}
海信空调:
public class HisenseHAVC implements Product{@Overridepublic void display() {System.out.println("海信空调");}
}
客户端使用:
public class Client {public static void main(String[] args) {//创建海尔的空调和电视AbstractFactory haierFactory = new HaierFactory();//客户端面向的是抽象Product tv = haierFactory.create("tv");Product hvac = haierFactory.create("hvac");tv.display();hvac.display();}
}
如果增加新的产品如冰箱,或者新增工厂如长虹电器,则需要改动的地方只有这里:

欢迎您的观看,有问题一起探讨。
相关文章:
设计模式篇---抽象工厂(包含优化)
文章目录 概念结构实例优化 概念 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。 工厂方法是有一个类型的产品,也就是只有一个产品的抽象类或接口,而抽象工厂相对于工厂方法来说,是有…...
Azure创建可用性集
什么是可用性集 在Azure中,可用性集(Availability Set)是一种用于提高虚拟机(VM)可用性和可靠性的功能。它通过将虚拟机分布在不同的物理硬件和故障域中来提供高可用性。每个故障域都是一个独立的电力和网络故障区域&…...
SpringBoot中优雅的实现隐私数据脱敏(提供Gitee源码)
前言:在实际项目开发中,可能会对一些用户的隐私信息进行脱敏操作,传统的方式很多都是用replace方法进行手动替换,这样会由很多冗余的代码并且后续也不好维护,本期就讲解一下如何在SpringBoot中优雅的通过序列化的方式去…...
Elasticsearch集群shard过多后导致的性能问题分析
1.问题现象 上午上班以后发现ES日志集群状态不正确,集群频繁地重新发起选主操作。对外不能正常提供数据查询服务,相关日志数据入库也产生较大延时 2.问题原因 相关日志 查看ES集群日志如下: 00:00:51开始集群各个节点与当时的master节点…...
Unity框架学习--5 事件中心管理器
作用:访问其它脚本时,不直接访问,而是通过发送一条“命令”,让监听了这条“命令”的脚本自动执行对应的逻辑。 原理: 1、让脚本向事件中心添加事件,监听对应的“命令”。 2、发送“命令”,事件…...
(二)结构型模式:3、过滤器模式(Filter、Criteria Pattern)(C++示例)
目录 1、过滤器模式(Filter、Criteria Pattern)含义 2、过滤器模式应用场景 3、过滤器模式主要几个关键角色 4、C实现过滤器模式的示例 1、过滤器模式(Filter、Criteria Pattern)含义 (1)过滤器模式是…...
谷歌在Chrome浏览器中推进抗量子加密技术
近日,Chromium博客上发表的一篇博文称,为了加强网络安全,应对迫在眉睫的量子计算机威胁,谷歌各个团队密切合作,为网络向抗量子密码学的过渡做好准备。 谷歌的Chrome团队在博客中写道,该项目涉及修订技术标准…...
Kotlin的数组
在 Kotlin 中,数组是一种固定大小的有序集合,可以存储相同类型的元素。Kotlin 提供了两种类型的数组:原生数组和数组类。以下是 Kotlin 中数组的详细使用方法: 1.创建数组 Kotlin 支持使用 arrayOf() 函数来创建数组:…...
centos 安装docker
1.更新你的系统: sudo yum update -y2.安装必需的软件包: Docker 需要 yum-utils, device-mapper-persistent-data 和 lvm2 软件包来运行。安装它们: sudo yum install -y yum-utils device-mapper-persistent-data lvm23.设置 Docker 的仓库: 使用以下命令添加 D…...
Oracle-如何判断字符串包含中文字符串(汉字),删除中文内容及保留中文内容
今天遇见一个问题需要将字段中包含中文字符串的筛选出来 --建表 CREATE TABLE HADOOP1.AAA ( ID VARCHAR2(255) ); --添加字段INSERT INTO HADOOP1.AAA(ID)VALUES(理解);....--查询表内容SELECT * FROM HADOOP1.AAA;在网上查找了一下有以下三种方式: 第一种&#…...
File 类的用法, InputStream和Reader, OutputStream和Writer 的用法
前言 普通的文件长这样: 其实目录也是一种特殊文件: 一、文件前缀知识 (一)绝对路径和相对路径 以盘符开头的的路径,叫做绝对路径,如:D:\360Downloads\cat.jpg 以.或..开头的路径,…...
AtCoder Beginner Contest 315 Task:A/B/C/E
A - tcdr 处理字符串简单题,题目要求去除字符串中的a,e,i,o,u即可 #include<iostream> using namespace std; int main() {string s;cin>>s;for(int i0;i<s.length();i){if(s[i]a||s[i]e||s[i]i||s[i]o||s[i]u)continue;cout<<s[i];} }B - T…...
【项目实践】基于LSTM的一维数据扩展与预测
基于LSTM的一维数据拟合扩展 一、引(fei)言(hua) 我在做Sri Lanka生态系统服务价值计算时,中间遇到了一点小问题。从世界粮农组织(FAO)上获得Sri Lanka主要农作物产量和价格数据时,其中的主要作物Sorghum仅有2001-2006年的数据,而Millet只有…...
webshell实践,在nginx上实现负载均衡
1、配置多台虚拟机,用作服务器 在不同的虚拟机上安装httpd服务 我采用了三台虚拟机进行服务器设置:192.168.240.11、192.168.240.12、192.168.240.13 [rootnode0-8 /]# yum install httpd -y #使用yum安装httpd服务#开启httpd服务 [rootnode0-8 /]# …...
LVS+Keepalived集群
keepalived Keepalived及其工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题 在一个LVS服务集群中通常有主服务器(MASTER)和备份服务器(BACKUP)两种角色的服务…...
Java的网络编程
网络编程 两台设备之间通过网络实现数据传输,将数据通过网络从一台设备传输到另一台设备 网络 两台或多台设备通过一定物理设备连接起来构成了网络 网络又分为: 局域网:覆盖范围最小,仅仅覆盖一个教室或一个机房城域网:覆盖范围较大,可以…...
kafka配置远程连接
要想实现在本地连接服务器的kafka,则必须在远程kafka配置远程连接 默认的 kafka 配置是无法远程访问的,解决该问题有几个方案。 方案1 advertised.listenersPLAINTEXT://IP:9092 注意必须是 ip,不能是 hostname 方案2 advertised.listene…...
css实现渐变色border
方式1 div {border: 4px solid;border-image: linear-gradient(to right, #8f41e9, #578aef) 1; }/* 或者 */ div {border: 4px solid;border-image-source: linear-gradient(to right, #8f41e9, #578aef);border-image-slice: 1; }作者:MudOnTire 链接:…...
管理 IBM Spectrum LSF
管理 IBM Spectrum LSF 了解如何管理 IBM Spectrum LSF 集群,控制守护程序,更改集群配置以及使用主机和队列。 管理 LSF 作业和作业调度策略。 查看作业信息和控制作业。 了解如何配置资源并将其分配给 LSF 作业。 了解如何在 LSF 集群中提交࿰…...
117页数字化转型与产业互联网发展趋势及机会分析报告PPT
导读:原文《》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 喜欢文章,您可以点赞评论转发本文,了解更多内容请私信:方…...
EagleEye效果实测:在JetPack 6.0 + Orin AGX上实现15ms推理的边缘部署方案
EagleEye效果实测:在JetPack 6.0 Orin AGX上实现15ms推理的边缘部署方案 如果你正在为边缘设备寻找一个又快又准的目标检测方案,那么今天的内容可能会让你眼前一亮。我们刚刚在NVIDIA Jetson Orin AGX上,基于最新的JetPack 6.0系统…...
深入解析CAN总线通信原理与CANoe实战开发指南
1. CAN总线通信原理深度剖析 CAN总线(Controller Area Network)是现代汽车电子系统中不可或缺的神经脉络。我第一次接触CAN总线是在2013年参与某新能源车项目时,当时就被它精巧的设计所震撼。与常见的串口通信不同,CAN采用差分信号…...
KMS_VL_ALL_AIO:智能激活脚本的高效办公解决方案
KMS_VL_ALL_AIO:智能激活脚本的高效办公解决方案 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 在数字化办公环境中,Windows系统和Office办公套件的激活管理常常成为用户…...
阿摩罗识CLAUDE.md内容的一些实践总结
环境安装 pip install keystone-engine capstone unicorn 这3个工具用法极其简单,下面通过示例来演示其用法。 Keystone 示例 from keystone import * CODE b"INC ECX; ADD EDX, ECX" try:ks Ks(KS_ARCH_X86, KS_MODE_64)encoding, count ks.asm(CODE)…...
别再让地图‘飘’了!深入浅出解析Cesium中GCJ-02、BD-09坐标偏移原理与DVGIS库实战
解密国内地图坐标系:从原理到实战解决Cesium中的“飘移”问题 你是否曾在Cesium中加载不同来源的地图数据时,发现明明标注的是同一个位置,却出现了明显的偏移?这种“飘移”现象背后,隐藏着国内地图坐标系复杂的加密体系…...
毫米波雷达(AWR1864)二、从零到一:SDK配置与固件刷写实战
1. 毫米波雷达开发环境搭建全攻略 第一次接触AWR1864毫米波雷达开发板时,最让人头疼的就是软件环境的配置。记得我刚开始用这块板子的时候,光是为了让开发板识别出来就折腾了大半天。这里给大家分享一个Windows系统下的完整配置方案,帮你避开…...
Video2X:用AI突破视频质量瓶颈的全栈解决方案
Video2X:用AI突破视频质量瓶颈的全栈解决方案 【免费下载链接】video2x A lossless video/GIF/image upscaler achieved with waifu2x, Anime4K, SRMD and RealSR. Started in Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/video…...
Mac清理工具Pearcleaner:残留文件处理与系统优化完全指南
Mac清理工具Pearcleaner:残留文件处理与系统优化完全指南 【免费下载链接】Pearcleaner Open-source mac app cleaner 项目地址: https://gitcode.com/gh_mirrors/pe/Pearcleaner Pearcleaner是一款免费开源的Mac应用清理工具,专为彻底卸载应用程…...
Tina Linux 适配 RTL8733bs WIFI 模块:从设备树到网络连接全流程解析
1. 硬件接口配置与设备树修改 第一次接触RTL8733bs这个Wi-Fi/蓝牙二合一模块时,我花了两天时间才搞明白硬件连接和设备树配置的关系。这个模块通过SDIO接口与全志V853主控通信,蓝牙部分则使用UART接口。下面我就把踩过的坑和验证过的正确配置分享给大家。…...
微信毕业设计基于微信小程序的易物小店交换系统
前言 Spring Boot 易物小店交换系统是一个基于 Web 的应用程序,利用 Spring Boot 框架构建,主要用于帮助用户实现物品交换的功能。该系统为用户提供了一个便捷、安全、高效的平台,让他们能够轻松地发布自己想要交换的物品信息,寻找…...
