学习理解Java工厂模式

学习理解Java工厂模式

  • 一、前言
  • 二、简单工程模式
  • 三、工厂方法模式
  • 四、抽象工厂模式
  • 五、静态工厂模式和 new 有什么区别?
  • 六、总结


一、前言

工厂模式目的是封装对象的创建过程,将对象的创建和使用分离开来,从而提高代码的可维护性和可扩展性。下面是它们之间的区别:

  1. 简单工厂模式:简单工厂模式是最简单的工厂模式,它将对象的创建过程封装在一个工厂类中,客户端通过工厂类来创建对象。简单工厂模式通常只有一个工厂类和多个产品类,客户端不需要关心具体的产品类,只需要知道它们的名称或类型即可。
  2. 工厂方法模式:工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。客户端通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换,符合开闭原则。
  3. 抽象工厂模式:抽象工厂模式是工厂方法模式的升级版,它定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换,符合开闭原则。

二、简单工程模式

简单工厂模式可以很好地隐藏对象创建的细节,使得客户端代码不必关心具体对象的创建过程。但是简单工厂模式也有缺点,例如当需要添加新的产品类时,就必须修改工厂类的代码,这违反了开闭原则。

public class AnimalFactory {public static Animal createAnimal(String type) {if (type.equals("Dog")) {return new Dog();} else if (type.equals("Cat")) {return new Cat();} else {throw new IllegalArgumentException("Invalid animal type: " + type);}}
}public interface Animal {void speak();
}public class Dog implements Animal {@Overridepublic void speak() {System.out.println("Woof!");}
}public class Cat implements Animal {@Overridepublic void speak() {System.out.println("Meow!");}
}public class Client {public static void main(String[] args) {Animal dog = AnimalFactory.createAnimal("Dog");Animal cat = AnimalFactory.createAnimal("Cat");Animal pig = AnimalFactory.createAnimal("pig");dog.speak(); // Output: Woof!cat.speak(); // Output: Meow!pig.speak(); // Output: Invalid animal type: pig}
}

三、工厂方法模式

工厂方法模式通常通过一个抽象工厂接口和多个具体工厂实现类来实现。

  1. 抽象工厂接口(Factory):定义了工厂方法的接口,声明了用于创建对象的方法,这些方法可以返回一个抽象产品类型或者一个具体产品类型。
  2. 具体工厂实现类(Concrete Factory):实现了抽象工厂接口中定义的方法,具体负责创建一组产品对象。
  3. 抽象产品接口(Product):定义了产品对象的通用接口,描述了产品对象的属性和方法。
  4. 具体产品实现类(Concrete Product):实现了抽象产品接口中定义的方法,是被工厂方法创建的对象。
// 抽象产品接口
interface Car {void run();
}// 具体产品实现类1
class Benz implements Car {@Overridepublic void run() {System.out.println("Benz is running.");}
}// 具体产品实现类2
class BMW implements Car {@Overridepublic void run() {System.out.println("BMW is running.");}
}// 抽象工厂接口
interface CarFactory {Car createCar();
}// 具体工厂实现类1
class BenzFactory implements CarFactory {@Overridepublic Car createCar() {return new Benz();}
}// 具体工厂实现类2
class BMWFactory implements CarFactory {@Overridepublic Car createCar() {return new BMW();}
}// 客户端代码
public class Client {public static void main(String[] args) {// 创建奔驰车CarFactory benzFactory = new BenzFactory();Car benzCar = benzFactory.createCar();benzCar.run();// 创建宝马车CarFactory bmwFactory = new BMWFactory();Car bmwCar = bmwFactory.createCar();bmwCar.run();}
}

四、抽象工厂模式

抽象工厂模式的核心思想是“工厂的工厂”。这意味着,不同的工厂可以创建不同的对象家族,而不是单个对象。这些工厂可以是具体的类,也可以是抽象类或接口。客户端使用这些工厂接口创建对象,而无需知道底层的实现细节。

// 定义抽象工厂接口
interface AbstractFactory {public ProductA createProductA();public ProductB createProductB();
}// 定义具体工厂类
class ConcreteFactory1 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA1();}public ProductB createProductB() {return new ConcreteProductB1();}
}class ConcreteFactory2 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA2();}public ProductB createProductB() {return new ConcreteProductB2();}
}// 定义产品接口
interface ProductA {public String getDescription();
}interface ProductB {public String getDescription();
}// 定义具体产品类
class ConcreteProductA1 implements ProductA {public String getDescription() {return "Product A1";}
}class ConcreteProductA2 implements ProductA {public String getDescription() {return "Product A2";}
}class ConcreteProductB1 implements ProductB {public String getDescription() {return "Product B1";}
}class ConcreteProductB2 implements ProductB {public String getDescription() {return "Product B2";}
}// 使用抽象工厂创建产品
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();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();}
}

在这个例子中,AbstractFactory 接口定义了两个方法 createProductAcreateProductB,用于创建产品 A 和产品 B。具体工厂类 ConcreteFactory1ConcreteFactory2 分别实现了这个接口,每个工厂都可以创建自己的一组产品。产品由 ProductAProductB 接口定义,而具体的产品类 ConcreteProductA1ConcreteProductA2ConcreteProductB1ConcreteProductB2 实现了这些接口。

五、静态工厂模式和 new 有什么区别?

在Java中,使用new关键字创建对象是主动获取资源的方式,应用与资源之间是直接依赖的。而采用工厂模式获取对象时,是应用向工厂要对象,工厂从容器中获取对象返回给应用,是被动的,从而降低了应用和资源之间的依赖关系。这种主动权的变化就叫控制反转。

静态工厂方法可以通过方法名字来表示创建了什么对象,比如下面这个方法,就表示创建一个可能是素数的BigInteger,所以,你可以通过名字来表明对象的作用。

总之,静态工厂模式和new创建对象有很大的区别。静态工厂模式可以降低应用和资源之间的依赖关系,使得代码更加灵活、可维护性更高;而new创建对象则是主动获取资源的方式。

六、总结

  1. 创建对象的方式不同:
  • 工厂方法模式:工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。客户端通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换。
  • 抽象工厂模式:抽象工厂模式定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换。
  1. 创建的对象类型不同:
  • 工厂方法模式:工厂方法模式适用于创建多种类型的产品对象。
  • 抽象工厂模式:抽象工厂模式适用于创建多个产品族的对象。
  1. 代码结构不同:
  • 工厂方法模式:工厂方法模式通常只需要一个工厂接口和多个具体工厂类,客户端只需要调用工厂接口的方法即可创建对象。
    抽象工厂模式:抽象工厂模式需要定义多个工厂接口和产品族接口,每个工厂接口和产品族接口都需要对应多个具体实现类,代码结构更加复杂。

  • 简单工厂模式适用于创建单一类型的产品对象,工厂方法模式适用于创建多种类型的产品对象,而抽象工厂模式适用于创建多个产品族的对象。

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

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

相关文章

腾讯云上linux系统使用nginx,flask构建个人网站SSL证书过期换证书的操作步骤

ssl证书过期的时候,一般腾讯云提前一段时间给通知,让更换ssl证书,现在一般都可以免费更换,一般是一年期的,审核通过之后,需要下载nginx版本的证书,我的是4个文件,替换到nginx/cert文…

【前端web入门第一天】01 开发环境、HTML基本语法文本标签

文章目录: 1. 准备开发环境 1.1 vs Code基本使用 2.HTML文本标签 2.1 标签语法2.2 HTML基本骨架2.3 标签的关系2.4 注释2.5 标题标签2.6 段落标签2.7 换行与水平线标签2.8 文本格式化标签 1. 准备开发环境 VSCode与谷歌浏览器离线版,安装包评论区自提. VSCode默认安装位置:C…

3、非数值型的分类变量

非数值型的分类变量 有很多非数字的数据,这里介绍如何使用它来进行机器学习。 在本教程中,您将了解什么是分类变量,以及处理此类数据的三种方法。 本课程所需数据集夸克网盘下载链接:https://pan.quark.cn/s/9b4e9a1246b2 提取码:uDzP 文章目录 1、简介2、三种方法的使用1…

书生·浦语大模型实战营-学习笔记5

LMDeploy 大模型量化部署实践 大模型部署背景 LMDeploy简介 轻量化、推理引擎、服务 核心功能-量化 显存消耗变少了 大语言模型是典型的访存密集型任务,因为它是decoder-by-decoder 先把数据量化为INT4存起来,算的时候会反量化为FP16 AWQ算法&a…

Angular组件(一) 分割面板ShrinkSplitter

Angular组件(一) 分割面板ShrinkSplitter 前言 分割面板在日常开发中经常使用,可将一片区域,分割为可以拖拽整宽度或高度的两部分区域。模仿iview的分割面板组件,用angular实现该功能,支持拖拽和[(ngModel)]双向绑定的方式控制区…

Docker容器引擎(2)

目录 一.批量删除镜像,容器 二.Docker 网络实现原理 随机映射端口(从32768开始) 访问自己: 在10服务器上配置路由转发: 指定映射端口: 查看容器的输出和日志信息: 将宿主机目标|文件挂载…

RabbitMQ中交换机的应用及原理,案例的实现

目录 一、介绍 1. 概述 2. 作用及优势 3. 工作原理 二、交换机Exchange 1. Direct 2. Topic 3. Fanout 三、代码案例 消费者代码 1. 直连direct 生产者代码 测试 2. 主题topic 生产者代码 测试 3. 扇形fanout 生产者代码 测试 每篇一获 一、介绍 1. …

Vue的生命周期方法

beforeCreate 在实例初始化之后,数据观测(data observe)和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。 created 实例已经创建完成之后被调用。在这一步,实…

【JavaEE进阶】 MyBatis使用注解实现增删改查

文章目录 🍃前言🌴传递参数🎋增(Insert)🚩返回主键 🎄删(Delete)🌲改(Update)🌳查(Select)🚩起别名🚩结果映射🚩开启驼峰命名(推荐使用) ⭕总结 &#x1f343…

使用curl测试响应式输出的接口

http://127.0.0.1:9010/v1/communicationRecord/summary 传递的json参数,是一个响应式的接口,怎么修改这个参数,可以响应式的输出。 为了使用curl命令对您的接口进行流式输出测试,您需要构造一个curl请求,该请求向您的…

[UI5 常用控件] 01.Text

文章目录 前言1. 普通文本2. 长文本:3. 设置最大显示行数 ( maxLines3 )4. 单行显示 ( wrappingfalse )5. 显示空白符 ( renderWhitespacetrue )6. 使用 - 连接单词:只适用于英文 ( wrappingTypeHyphenated )7. 空白时使用 - 代替 ( emptyIndicatorModeOn )8. JSON数…

行内样式css不生效

场景&#xff1a; 别人的代码里有样式是写在行内的&#xff0c;且设置了display:block&#xff1b;没有生效&#xff0c;也没有被覆盖样式&#xff0c;很奇怪。 <span style"width:90px;display:block;">很多字&#xff0c;style也很长&#xff0c;中间换行了…

2024年需要重点关注的15种计算机病毒

2024年&#xff0c;计算机病毒威胁变得愈发多元化和复杂化。涉及勒索病毒、二维码病毒、挖矿木马等15种类型&#xff0c;这些病毒从数据勒索到系统入侵&#xff0c;对全球网络安全构成严峻挑战。 2024年&#xff0c;计算机病毒威胁变得愈发多元化和复杂化。涉及勒索病毒、二维码…

【网络安全】常见的网络威胁有哪些?

随着互联网的快速发展&#xff0c;网络安全问题日益凸显。常见的网络威胁包括病毒、木马、恶意软件等。这些威胁不仅会影响计算机的安全运行&#xff0c;还会窃取用户的个人信息&#xff0c;造成巨大的损失。因此&#xff0c;我们需要采取一些措施来保护自己的网络安全。 常见的…

ardupilot 方向余弦矩阵/旋转矩阵的理解

目录 文章目录 目录摘要1.序言2.方向余弦矩阵2.1 方向余弦矩阵定义2.2 方向余弦矩阵的特点2.3 方向余弦矩阵微分方程2.4 方向余弦矩阵微分方程求解摘要 本节主要记录自己对ardupilot中用到的方向余弦矩阵/旋转矩阵的理解,欢迎批评指正,有些资料参考网上写的比较好的资料,免…

深入理解Java LinkedList:使用场景与实际应用

深入理解Java LinkedList&#xff1a;使用场景与实际应用 在Java的世界里&#xff0c;集合框架是不可或缺的一部分&#xff0c;它提供了一系列用于存储和操作数据集合的接口和类。其中&#xff0c;LinkedList作为List接口的一个实现&#xff0c;经常被拿来与ArrayList做对比。…

android 图片添加水印

android 图片添加水印 本文主要讲下android 中如何给图片添加水印. 在Android中给图片添加水印可以使用Bitmap、Matrix和Canvas类的方法来实现. private Bitmap addWater() {// 加载原始图片Bitmap sourceBitmap BitmapFactory.decodeResource(getResources(), R.mipmap.sou…

Vue+OpenLayers7:OpenLayers7地图初始化时如何设置默认缩放级别、设置默认地图中心点、最大缩放级别和最小缩放级别以及默认坐标系

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7 本章讲解OpenLayers7地图初始化时如何设置默认缩放级别、设置默认地图中心点、最大缩放级别和最小缩放级别以及默认坐标系等配置。 前言 OpenLayers7地图初始化时如何设置默认缩放级别、初始化时设置默认地图中心点、设置…

启动mitmproxy报错 ImportError: cannot import name ‘url_quote‘ from ‘werkzeug.urls‘

报错截图 ImportError: cannot import name url_quote from werkzeug.urls (d:\soft\python\python38\lib\site-packages\werkzeug\urls.py) 原因是Werkzeug版本不兼容导致 解决方法 pip install Werkzeug2.2.2

大数据学习之Flink算子、了解(Source)源算子(基础篇二)

Source源算子&#xff08;基础篇二&#xff09; 目录 Source源算子&#xff08;基础篇二&#xff09; 二、源算子&#xff08;source&#xff09; 1. 准备工作 2.从集合中读取数据 可以使用代码中的fromCollection()方法直接读取列表 也可以使用代码中的fromElements()方…