Java面试题:通过实例说明工厂模式和抽象工厂模式的用法,以及它们在解耦中的作用
工厂模式和抽象工厂模式是创建型设计模式中的两种,主要用于对象的创建,并且通过将对象的创建过程封装起来,来实现代码的解耦和灵活性。下面通过具体实例来说明这两种模式的用法及其在解耦中的作用。
工厂模式(Factory Method Pattern)
工厂模式通过定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
实例说明
假设我们有一个交通工具接口 Vehicle 以及具体实现类 Car 和 Bike。我们通过工厂模式来创建这些交通工具对象。
接口和实现类
// Vehicle.java
public interface Vehicle {void drive();
}// Car.java
public class Car implements Vehicle {@Overridepublic void drive() {System.out.println("Driving a car.");}
}// Bike.java
public class Bike implements Vehicle {@Overridepublic void drive() {System.out.println("Riding a bike.");}
工厂类
// VehicleFactory.java
public abstract class VehicleFactory {public abstract Vehicle createVehicle();
}// CarFactory.java
public class CarFactory extends VehicleFactory {@Overridepublic Vehicle createVehicle() {return new Car();}
}// BikeFactory.java
public class BikeFactory extends VehicleFactory {@Overridepublic Vehicle createVehicle() {return new Bike();}
使用工厂模式
public class Main {public static void main(String[] args) {VehicleFactory carFactory = new CarFactory();Vehicle car = carFactory.createVehicle();car.drive(); // 输出: Driving a car.VehicleFactory bikeFactory = new BikeFactory();Vehicle bike = bikeFactory.createVehicle();bike.drive(); // 输出: Riding a bike.}
}
解耦作用
通过工厂模式,Main 类不需要知道具体的交通工具类,只需要知道工厂类和接口 Vehicle。这使得代码更加灵活,增加了新类型的交通工具时不需要修改现有代码。
抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
实例说明
假设我们有一个家具工厂,可以创建椅子和沙发。我们通过抽象工厂模式来实现。
接口和实现类
// Chair.java
public interface Chair {void sitOn();
}// Sofa.java
public interface Sofa {void lieOn();
}// VictorianChair.java
public class VictorianChair implements Chair {@Overridepublic void sitOn() {System.out.println("Sitting on a Victorian chair.");}
}// ModernChair.java
public class ModernChair implements Chair {@Overridepublic void sitOn() {System.out.println("Sitting on a modern chair.");}
}// VictorianSofa.java
public class VictorianSofa implements Sofa {@Overridepublic void lieOn() {System.out.println("Lying on a Victorian sofa.");}
}// ModernSofa.java
public class ModernSofa implements Sofa {@Overridepublic void lieOn() {System.out.println("Lying on a modern sofa.");}
抽象工厂类和具体工厂类
// FurnitureFactory.java
public interface FurnitureFactory {Chair createChair();Sofa createSofa();
}// VictorianFurnitureFactory.java
public class VictorianFurnitureFactory implements FurnitureFactory {@Overridepublic Chair createChair() {return new VictorianChair();}@Overridepublic Sofa createSofa() {return new VictorianSofa();}
}// ModernFurnitureFactory.java
public class ModernFurnitureFactory implements FurnitureFactory {@Overridepublic Chair createChair() {return new ModernChair();}@Overridepublic Sofa createSofa() {return new ModernSofa();}
}
使用抽象工厂模式
public class Main {public static void main(String[] args) {FurnitureFactory victorianFactory = new VictorianFurnitureFactory();Chair victorianChair = victorianFactory.createChair();Sofa victorianSofa = victorianFactory.createSofa();victorianChair.sitOn(); // 输出: Sitting on a Victorian chair.victorianSofa.lieOn(); // 输出: Lying on a Victorian sofa.FurnitureFactory modernFactory = new ModernFurnitureFactory();Chair modernChair = modernFactory.createChair();Sofa modernSofa = modernFactory.createSofa();modernChair.sitOn(); // 输出: Sitting on a modern chair.modernSofa.lieOn(); // 输出: Lying on a modern sofa.}
}
解耦作用
抽象工厂模式通过将具体工厂类与产品对象的创建过程分离,使得客户端代码仅依赖于工厂接口和产品接口。这样,增加新的家具风格时,只需添加新的具体工厂类和产品类,不需要修改现有代码。这种方式大大提高了系统的扩展性和可维护性。
总结
- 工厂模式通过定义一个创建对象的接口,使得具体类的实例化过程延迟到子类,从而实现了创建对象的灵活性和代码的解耦。
- 抽象工厂模式则进一步扩展,通过提供一个创建一系列相关或相互依赖对象的接口,使得产品族的创建过程独立于客户端代码,极大地提高了系统的可扩展性和可维护性。
两种模式都通过将对象的创建过程封装起来,实现了代码的解耦,使得系统更加灵活、易于扩展和维护。
相关文章:
Java面试题:通过实例说明工厂模式和抽象工厂模式的用法,以及它们在解耦中的作用
工厂模式和抽象工厂模式是创建型设计模式中的两种,主要用于对象的创建,并且通过将对象的创建过程封装起来,来实现代码的解耦和灵活性。下面通过具体实例来说明这两种模式的用法及其在解耦中的作用。 工厂模式(Factory Method Pat…...
成都欣丰洪泰文化传媒有限公司电商服务的创新者
在数字化浪潮席卷全球的今天,电商行业正以前所未有的速度蓬勃发展。作为这一领域的佼佼者,成都欣丰洪泰文化传媒有限公司凭借其对电商服务的深度理解和精准把握,成功在竞争激烈的市场中脱颖而出,成为行业内的佼佼者。 一、公司简…...
学习笔记——动态路由——RIP(距离矢量协议)
一、距离矢量协议 1、距离矢量协议 矢量行为:协议收到一个路由之后,查看是否可以加入到本地的路由表中,如果可以加入,则可以传递,如果不可以加入,则无法传递。 距离矢量路由协议 RIP基于距离矢量算法(又…...
【python】OpenCV—Segmentation
文章目录 cv2.kmeans牛刀小试 cv2.kmeans cv2.kmeans 是 OpenCV 库中用于执行 K-Means 聚类算法的函数。以下是根据参考文章整理的 cv2.kmeans 函数的中文文档: 一、函数功能 cv2.kmeans 用于执行 K-Means 聚类算法,将一组数据点划分到 K 个簇中&…...
python-题库篇-Python语言特性
文章目录 Python语言特性1 Python的函数参数传递2 Python中的元类(metaclass)3 staticmethod和classmethod4 类变量和实例变量5 Python自省6 字典推导式7 Python中单下划线和双下划线8 字符串格式化:%和.format9 迭代器和生成器10 *args and **kwargs11 面向切面编程AOP和装饰器…...
WEB界面上使用ChatGPT
(作者:陈玓玏) 开源项目,欢迎star哦,https://github.com/tencentmusic/cube-studio 随着大模型不断发展,现在无论写代码,做设计,甚至老师备课、评卷都可以通过AI大模型来实现了&…...
【Matlab】CNN-LSTM分类 卷积神经网络-长短期记忆神经网络组合模型(附代码)
资源下载: https://download.csdn.net/download/vvoennvv/89466499 分类算法资源合集:https://download.csdn.net/download/vvoennvv/89466519 目录 Matlab SVM支持向量机分类算法 Matlab RF随机森林分类算法 Matlab RBF径向基神经网络分类算法 Ma…...
性能工具之 MySQL OLTP Sysbench BenchMark 测试示例
文章目录 一、前言二、测试环境1、服务器配置2、测试拓扑 三、测试工具安装四、测试步骤1、导入数据2、压测数据3、清理数据 五、结果解析六、最后 一、前言 做为一名性能工程师掌握对 MySQL 的性能测试是非常必要的,本文基于 Sysbench 对MySQL OLTP(联…...
【QT】QCustomPlot库中iSelectPlottables的使用
QCP::iSelectPlottables 是 QCustomPlot 库中的一个枚举值,用于控制选择交互。QCustomPlot 是一个用于创建绘图和数据可视化的Qt库。 QCP::iSelectPlottables 允许用户选择图表中的绘图对象(如图形、曲线、柱状图等)。 应用场景 QCP::iSele…...
字节跳动联手博通:5nm AI芯片诞生了?
字节跳动联手博通:5nm AI芯片诞生了? 前言 就在6月24日,字节跳动正在与美国博通合作开发一款5纳米工艺的专用集成电路(ASIC) AI处理器。这款芯片旨在降低采购成本并确保高端AI芯片的稳定供应。 根据报道,尽管芯片设计工作进展顺利…...
【数据结构与算法】动态查找表(二叉排序树,二叉平衡树)详解
二叉排序树的数据结构。 struct TreeNode {ElemType data;TreeNode *left, *right; }; using BiTree TreeNode *;结构体包含三个成员: data 是一个 ElemType 类型的变量,用于存储二叉搜索树节点的数据。left 是一个指向 TreeNode 类型的指针ÿ…...
PyTorch中“No module named ‘torch._six‘“的报错场景及处理方法
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引入 在使用PyTorch时,您可能会遇到"No module named ‘torch._six’"的错误。这通常是因为PyTorch的某些…...
Spring Boot 集成 MinIO 实现文件上传
Spring Boot 集成 MinIO 实现文件上传 一、 Minio 服务准备 MinIO的搭建过程参考 Docker 搭建 MinIO 对象存储。 登录MinIO控制台,新建一个 Bucket,修改 Bucket 权限为公开。 二、MinIO 集成 添加 MinIO 依赖 <!-- https://mvnrepository.com/ar…...
目标跟踪——KCF源码用python实现
from numpy.fft import fft2, ifft2, fftshift import cv2 import numpy as npclass HOG:def __init__(self, winSize):""":param winSize: 检测窗口的大小"""self.winSize winSizeself.blockSize (8, 8)self.blockStride (4, 4)self.cellSiz…...
前端 转换笔记
<!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>转换</title> <style> .box{ /* 盒子摆在body的正中间 */ position: absolut…...
个人开发笔记
开发笔记 开发常见问题Vue开发中页面flex滚动布局,内容置顶问题功能快捷键 开发常见问题 Vue开发中页面flex滚动布局,内容置顶问题 直接操作路由: const router createRouter({routes: routes,history: createWebHashHistory(),scrollBeha…...
pdf压缩,pdf压缩在线,pdf文件太大怎么变小
在数字化时代,PDF文档因其跨平台、保持原样、易于阅读和打印等特点,成为了我们日常工作和生活中不可或缺的一部分。然而,随着PDF文件的不断累积,存储空间逐渐变得紧张,特别是在处理大量大型PDF文件时,如何有…...
Go 如何使用指针灵活操作内存
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
【面试干货】Java中的++操作符与线程安全性
【面试干货】Java中的操作符与线程安全性 1、什么是线程安全性?2、 操作符的工作原理3、 操作符与线程安全性4、如何确保线程安全?5、 结论 💖The Begin💖点点关注,收藏不迷路💖 在Java编程中,操…...
NLP学习与踩坑记录(持续更新版)
NLP学习与踩坑记录(持续更新版) OSError: Cant load tokenizer for bert-base-uncased.google.protobuf.message.DecodeError: Error parsing messageDeepspeed 本博客记录了博主在学习NLP时遇到了各种各样的问题与解决方法,供大家参考&#…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
