Java设计模式 —— 【创建型模式】工厂模式(简单工厂、工厂方法模式、抽象工厂)详解
文章目录
- 前言
- 一、简单工厂(静态工厂)
- 1、概述
- 2、代码实现
- 3、优缺点
- 二、工厂方法模式
- 1、概述
- 2、代码实现
- 3、优缺点
- 三、抽象工厂模式
- 1、概述
- 2、代码实现
- 3、优缺点
- 四、总结
前言
先看个案例:【手机和手机店】在没有工厂的时候,手机店需要手机就需要自己创建,还得根据用户的选择进行创建不同的手机,如下图:
这样手机店直接与手机对象接触,就会对该对象耦合严重,假如我们添加新的手机品牌,还得修改手机店的create方法,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,将对象的创建封装在工厂内,实现使用者和对象解耦;所以说,工厂模式最大的优点就是:解耦。
工厂模式的主要目的是将对象的创建过程封装在工厂类中,客户端代码只需要关心从工厂获取对象的过程,而不需要了解对象的创建细节。这样可以降低代码的耦合度,提高代码的可维护性和可扩展性
一、简单工厂(静态工厂)
1、概述
简单工厂不是一种设计模式,反而比较像是一种编程习惯。把对象的创建和业务逻辑层分开,实现使用方(手机店)与对象(手机)的解耦。但工厂和产品之间还是存在耦合关系。
主要包含以下角色:
- 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品: 实现或者继承抽象产品的子类
- 具体工厂: 提供了创建产品的方法,调用者通过该方法来获取产品。
2、代码实现
抽象手机类【抽象产品】:
public abstract class Phone {public abstract String getName();
}
手机产品【具体产品】:
public class HuaWei extends Phone {@Overridepublic String getName() {return "华为手机";}
}public class XiaoMi extends Phone {@Overridepublic String getName() {return "小米手机";}
}
手机工厂【具体工厂】:
public class Factory {public static Phone createPhone(String name) {Phone phone = null;if("小米".equals(name)) {phone = new XiaoMi();} else if("华为".equals(name)) {phone = new HuaWei();}return phone;}
}
手机店【使用者】:
public class Sotre {public static Phone orderPhone(String name) {return Factory.createPhone(name);}
}
测试:
public class Test {public static void main(String[] args) {Phone xiaomi = Sotre.orderPhone("小米");System.out.println(xiaomi.getName());Phone huawei = Sotre.orderPhone("华为");System.out.println(huawei.getName());}
}
3、优缺点
优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。
二、工厂方法模式
1、概述
在在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体的工作交给子类去做。 定义一个用于创建对象的接口(抽象工厂),让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。很好的解决了简单工厂的问题,遵循开闭原则。
工厂方法模式的主要角色:
- 抽象工厂: 提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
- 具体工厂: 主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品: 实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
2、代码实现
抽象手机类【抽象产品】:
public abstract class Phone {public abstract String getName();
}
手机产品【具体产品】:
//小米手机
public class XiaoMi extends Phone {@Overridepublic String getName() {return "小米手机";}
}//华为手机
public class HuaWei extends Phone {@Overridepublic String getName() {return "华为手机";}
}
抽象工厂:
class interface PhoneFactory {Phone createPhone();
}
具体工厂:
//小米工厂
public class XiaoMiFactory implements PhoneFactory {@Overridepublic Phone createPhone() {return new XiaoMi();}
}//华为工厂
public class HuaWeiFactory implements PhoneFactory {@Overridepublic Phone createPhone() {return new HuaWei();}
}
手机店【使用者】:
public class Store {public Phone orderPhone(PhoneFactory factory) {return factory.createPhone();}
}
测试:
public class Test {public static void main(String[] args) {Store store = new Store();Phone huaWei = store.orderPhone(new HuaWeiFactory());Phone xiaomi = store.orderPhone(new XiaoMiFactory());System.out.println(xiaomi.getName());System.out.println(huaWei.getName());}
}
3、优缺点
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
三、抽象工厂模式
1、概述
抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产同一个等级的产品(小米手机,华为手机),而抽象工厂模式可生产多个等级的产品(小米家族,华为家族)。
抽象工厂模式的主要角色如下:
- 抽象工厂: 提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品(小米工厂和华为工厂的所有功能的抽象【创建手机,创建路由器】)。
- 具体工厂: 主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建(小米工厂造小米家族产品,华为工厂造华为家族产品)。
- 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品(小米和华为所拥有的同一系列产品的抽象【手机产品,路由器产品】)。
- 具体产品: 实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
2、代码实现
抽象工厂:
public interface Factory {// 生产手机Phone createPhone();// 生产路由器Router createRouter();
}
具体工厂:
//小米工厂
public class XiaoMiFactory implements Factory {@Overridepublic Phone createPhone() {return new XiaoMiPhone();}@Overridepublic Router createRouter() {return new XiaoMiRouter();}
}//华为工厂
public class HuaWeiFactory implements Factory {@Overridepublic Phone createPhone() {return new HuaWeiPhone();}@Overridepublic Router createRouter() {return new HuaWeiRouter();}
}
抽象产品:
//手机产品
public abstract class Phone {public abstract String getName();
}//路由器类
public abstract class Router {public abstract String getName();
}
具体产品:
public class XiaoMiPhone extends Phone{@Overridepublic String getName() {return "小米手机";}
}public class HuaWeiPhone extends Phone {@Overridepublic String getName() {return "华为手机";}
}
public class XiaoMiRouter extends Router {@Overridepublic String getName() {return "小米路由器";}
}public class HuaWeiRouter extends Router {@Overridepublic String getName() {return "华为路由器";}
}
手机店:
public class Store {private Factory factory;public void setFactory(Factory factory) {this.factory = factory;}public Phone orderPhone(){return factory.createPhone();}public Router orderRouter(){return factory.createRouter();}
}
测试:
public class Test {public static void main(String[] args) {Store store = new Store();store.setFactory(new XiaoMiFactory());Phone xiaomiPhone = store.orderPhone();Router xiaomiRouter = store.orderRouter();System.out.println(xiaomiPhone.getName());System.out.println(xiaomiRouter.getName());System.out.println("===========");store.setFactory(new HuaWeiFactory());Phone huaweiPhone = store.orderPhone();Router huaweiRouter = store.orderRouter();System.out.println(huaweiPhone.getName());System.out.println(huaweiRouter.getName());}
}
如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。
3、优缺点
优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:
当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
四、总结
- 以上述案例为例,没有工厂就是手机店直接造手机,使用者和对象高度耦合,新增品类时违背开闭原则,一个手机店造不同手机违背单一职责原则;
- 由此引出简单工厂,手机店只需要和工厂打交道,售卖手机,不负责造手机的过程,实现手机店和对象的解耦,但是工厂和对象还是存在上述问题;
- 由此工厂在向上抽象出“工厂规范”,形成工厂方法模式,不同的工厂负责不同的职责,添加新的品类时增加对应工厂和产品即可;
- 在往下走,工厂做大做强以后,不只是可以生产手机,还添加了新的产品路由器,形成抽象工厂模式。
- 工厂方法模式是针对单一的品类进行的实现,二抽象工厂是针对多个品类(产品族)的实现。
相关文章:
Java设计模式 —— 【创建型模式】工厂模式(简单工厂、工厂方法模式、抽象工厂)详解
文章目录 前言一、简单工厂(静态工厂)1、概述2、代码实现3、优缺点 二、工厂方法模式1、概述2、代码实现3、优缺点 三、抽象工厂模式1、概述2、代码实现3、优缺点 四、总结 前言 先看个案例:【手机和手机店】在没有工厂的时候,手…...
KST-3D01型胎儿超声仿真体模、吸声材料以及超声骨密度仪用定量试件介绍
一、KST-3D01型胎儿超声仿真体模 KST—3D01型胎儿超声体模,采用仿羊水环境中内置胎龄为7个月大仿胎儿设计。用于超声影像系统3D扫描演示装置表面轮廓呈现和3D重建。仿羊水超声影像呈暗回声(无回波)特性,仿胎儿超声影像呈对比明显…...
网络原理->DNS协议和NAT协议解
前言 大家好我是小帅,今天我们来了解应用层的DNS协议和NAT技术 个人主页:再无B~U~G 文章目录 1.重要应⽤层协议DNS(Domain Name System)1.1 DNS背景 2. NAT技术3. 总结 1.重要应⽤层协议DNS(Domain Name System) DNS是⼀整套从域…...
基于yolov8、yolov5的100种中药材检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
项目介绍 项目中所用到的算法模型和数据集等信息如下: 算法模型: yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 , 直接提供最少两个训练好的模型。模型十分重要,因为有些同学的电脑没有 GPU࿰…...
RuoYi排序
RuoYi框架提供了多种实现排序的方法,以满足不同场景下的需求。这里简要介绍几种常见的排序实现方式: 1. 后端排序 1.1 使用startPagePlus方法 RuoYi框架中,可以通过对BaseController进行扩展来实现更灵活的分页与排序功能。例如࿰…...
Python+Pytest+Yaml+Allure数据参数化(DDT)数据驱动(一)
我们在做数据之前要知道几个问题 1、在代码层面怎么来数据驱动 2、yaml文件是什么 3、怎么用yaml文件实现对应的数据驱动 我们用的是pytest框架所以相对来说是简单的,我们通过pytest框架来实现,而框架中要数据驱动用到我们装饰器就好啦pytest.mark.p…...
BASLER工业相机维修不能触发拍照如何处理解决这个问题
BASLER工业相机维修不能触发拍照如何处理解决这个问题?最近遇到挺多工业相机维修咨询这个不能触发拍照的案例,所以今天优米佳维修的技术就抽空整理了这篇关于BASLER相机不能触发拍照的处理方法分享给大家。 当碰到巴斯勒工业相机不能触发拍照的问题&…...
Could not locate device support files.
报错信息:Failure Reason: The device may be running a version of iOS (13.6.1 17G80) that is not supported by this version of Xcode.[missing string: 869a8e318f07f3e2f42e11d435502286094f76de] 问题:xcode15升级到xcode16之后,13.…...
linux系统中常用文件日常使用命令记录
我们办公机是Ubuntu系统; 记录下工作中经常使用的几个文件或命令或一些零碎的知识点: (该文档会持续更新) 查看系统信息: uname -a cat /etc/product-info cat /etc/os-version 存放系统启停脚本 /etc/init.d/ 存放源…...
【C++打怪之路Lv16】-- map set
🌈 个人主页:白子寰 🔥 分类专栏:重生之我在学Linux,C打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您的订阅和支持~ 💡 坚持…...
TPU-MLIR 项目源码结构分析
TPU-MLIR 项目源码结构分析 本文用作学习记录和交流分享,主要内容为 TPU-MLIR 的源码框架分析和构建流程分析。源码地址:https://github.com/sophgo/tpu-mlir 文件结构 从最外层开始分析 envsetup.sh 该脚本用于配置和初始化开发环境,其中…...
IDEA Maven 打包找不到程序包错误或找不到符号,报错“程序包不存在“
参考文章:https://blog.csdn.net/yueeryuanyi/article/details/14211090 问题:IDEA Maven 打包找不到程序包错误或找不到符号,报错“程序包不存在“编译都没问题 解决思路 – >【清除缓存】 1. 强制刷新Maven缓存 选择 Maven 标签,Exe…...
Sourcetree:一款强大的Git客户端
Sourcetree:一款强大的Git客户端 Sourcetree是一款由Atlassian开发的免费Git客户端,它提供了一个直观的图形界面,让用户能够轻松地管理他们的版本控制系统。无论是初学者还是有经验的开发者,Sourcetree都能提供方便快捷的Git操作…...
Linux环境变量与本地变量
文章目录 Linux环境变量与本地变量什么是环境变量查看环境变量设置环境变量本地变量命令行参数 Linux环境变量与本地变量 什么是环境变量 操作系统或运行时环境中存储的一些变量,用来存储与进程或系统相关的配置信息。这些变量在进程启动时由操作系统或Shell读取&…...
ChatGPT的应用场景:开启无限可能的大门
ChatGPT的应用场景:开启无限可能的大门 随着人工智能技术的快速发展,自然语言处理领域迎来了前所未有的突破。其中,ChatGPT作为一款基于Transformer架构的语言模型,凭借其强大的语言理解和生成能力,在多个行业和场景中展现出了广泛的应用潜力。以下是ChatGPT八个最具代表…...
QT按下两次按钮,保存这期间内变换的QtextEdit控件内的数据
这个功能在项目中很常见,对界面里某个控件的数据进行记录,我这个是每秒记录5次,实际就是每200ms触发一次定时器,来满足需求。 .h文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QtSerialPort> …...
daos源码编译
1. 前言 本文详细介绍如何在almalinux8.9上编译daos.2.0.0源码。系统环境如下: daos: 2.0.0 linux os: almalinux 8.9 linux kernel: 4.18.0-513.5.1.el8_9.x86_64之所以选择2.0.0版本,是因为daos从2.0.0开始是一个全新的架构设计&a…...
HTML飞舞的爱心
目录 系列文章 写在前面 完整代码 代码分析 写在后面 系列文章 序号目录1HTML满屏跳动的爱心(可写字)2HTML五彩缤纷的爱心3HTML满屏漂浮爱心4HTML情人节快乐5HTML蓝色爱心射线6HTML跳动的爱心(简易版)7HTML粒子爱心8HTML蓝色…...
C++中智能指针的使用及其原理 -- RAII,内存泄漏,shared_ptr,unique_ptr,weak_ptr
目录 1.智能指针的使用场景分析 2.RAII和智能指针的设计思路 3.C标准库智能指针的使用 4.智能指针的原理以及模拟实现 5.shared_ptr循环引用问题和weak_ptr 5.1shared_ptr循环引用问题 5.2weak_ptr的原理和部分接口 5.3weak_ptr的简单模拟实现 6. shared_ptr的线程安…...
Linux服务器安装mongodb
因为项目需要做评论功能,领导要求使用mongodb,所以趁机多学习一下。 在服务器我们使用docker安装mongodb 1、拉取mongodb镜像 docker pull mongo (默认拉取最新的镜像) 如果你想指定版本可以这样 docker pull mongo:4.4&#…...
Android11修改摄像头前后置方法,触觉智能RK3568开发板演示
本文介绍在Android11系统下,修改摄像头前后置属性的方法。使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统&#…...
leetcode 212. 单词搜索 II
给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。 单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一…...
Taro 鸿蒙技术内幕系列(三) - 多语言场景下的通用事件系统设计
基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章将深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕 背景 在鸿蒙生态系统中,虽然原生应用通常基于 ArkTS 实现,但在实际研发过程中发现,使用 C…...
《Docker Registry(镜像仓库)详解》
一、引言 在容器化技术日益普及的今天,Docker 已成为众多开发者和企业的首选工具。而 Docker Registry(镜像仓库)作为 Docker 生态系统中的重要组成部分,负责存储和分发 Docker 镜像。本文将深入探讨 Docker Registry 的概念、功能…...
AI前景分析展望——GPTo1 SoraAI
引言 人工智能(AI)领域的飞速发展已不仅仅局限于学术研究,它已渗透到各个行业,影响着从生产制造到创意产业的方方面面。在这场技术革新的浪潮中,一些领先的AI模型,像Sora和OpenAI的O1,凭借其强大…...
超级详细讲解转义字符,\? \‘ \f \0 \t等等!!!
C语言有一组特殊的字符称作转义字符,顾名思义,转变原来的意思 1 \? ??)是一个三字母词,在以前的编译器它会被编译为] (??会被编译为[ 因此在以前输入(are you ok ??)就会被编译为are you ok ] 解决这个问题只要在问号前输入\…...
微信小程序数据请求教程:GET与POST请求详解
微信小程序数据请求教程:GET与POST请求详解 引言 在微信小程序的开发过程中,数据请求是至关重要的一部分。通过与后端服务器进行通信,小程序能够获取动态数据,实现丰富的功能。在这篇文章中,我们将深入探讨微信小程序中的数据请求,重点介绍GET和POST请求的使用方法、示…...
Linux系统管理基础指南--习题
目录 一、基础知识与命令 二、 Linux的用户接口 三、文件权限与目录管理 四、shell相关知识 五、软件安装与网络 六、网络进程管理 一、基础知识与命令 1. (操作题)分别执行下述命令 ls -al cd ~ cd man -f man man –k cd man --help cal --help date --help bc --he…...
JVM(JAVA虚拟机)内存溢出导致内存不足,Java运行时环境无法继续
1、先贴出服务最后打印出来的日志,意思就是给虚拟机分配的内存被用完了,没有可用的内存了,服务运行不了了,被动停服了。详细的日志记录在了/home/user/zx/tomcat/apache-tomcat-8.5.82/bin/hs_err_pid147951.log文件里。 Java Ho…...
IOC控制反转详解
IOC(控制反转) component的衍生注解 前面曾经提到,若想要把某个对象交给IOC容器管理,就需要在其声明上加上Component注解。但是Spring中有三层架构,为了更加清晰的标注对象是属于哪一层的,提供了三个Comp…...
做网站排名软件/太原整站优化排名外包
java类中的argument list 若为 "Object...args" 如 public StringResult isValid(Object... args) 意为有不定数目的Object 类型 的argument转载于:https://www.cnblogs.com/weeky/archive/2012/10/14/2723448.html...
哪些网站可以做画赚钱/百度竞价推广方法
目录 前言 一、创建快捷方式 二、选择你的自定义图标 1. 下载png图 2. 获取ico图标文件 三、更改快捷方式图标 前言 今天在Windows10下安装了Spyder编辑器,好用归好用,但是在创建快捷方式后面对那类似于IDLE的图标实在是左右看着都难受࿰…...
武威网站建设价格/友情链接检查工具
Linux下IPTABLES防火墙的设定安装linux后(防火墙是开启状态),需要检查防火墙端口1.iptables防火墙启动和停止启动iptables防火墙时命令行输入 #service iptables start[roothost.jefflei.com ~]# service iptables start应用 iptables 防火墙规则: …...
上海企业建设网站电话/办公软件速成培训班
点击上方 "Python人工智能编程" 关注,星标或者置顶每天11点准时推送,第一时间送达来自:量子位 报道 | 公众号 QbitAI | 编辑:真经君正文你是否也在朋友圈看过这样的小推广:「你要悄悄学Python,然…...
本科自考助学班/青岛seo计费
今天,移动支付领域迈出了新的一步:万事达卡和德国电信宣布,二者将携手沿着德国电信的业务足迹在欧洲推出移动支付,今年第三季度将在波兰推出NFC钱包解决方案,不久之后再推广到德国。不过目前美国市场还不在考虑范围内。…...
web成品网站下载/站长之家查询网站
先明确两个概念: * 事务:事务必须符合ACID特性 * 单行:一行数据中包含多个列(column),一个事务中可以操作同一行中的多个列,在操作过程中保证ACID。 * 单行事务:仅要求单行数据符…...