java设计模式 -- 工厂模式

1、基本概念

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。

工厂模式属于创建型模式,它在创建对象时提供了一种封装机制,将实际创建对象的代码与使用代码分离。

应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、在 Hibernate 中,如果需要更换数据库,工厂模式同样发挥了作用。只需简单地更改方言(Dialect)和数据库驱动(Driver),就能够实现对不同数据库的切换。

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。

2、简单工厂模式

我们将创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory

FactoryPatternDemo 类使用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。

优点是比较好理解,简单易操作。

缺点是类的创建依赖工厂类,如果想要拓展程序,必须对工厂类进行修改,这违反了设计模式的开闭原则(OCP),即对扩展开放,对修改关闭。

步骤 1:创建一个接口。

package com.hh.model.factory;public interface Shape {void draw();
}

步骤 2:创建实现接口的实体类。

package com.hh.model.factory;public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}
package com.hh.model.factory;public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}
package com.hh.model.factory;public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

步骤 3:创建一个工厂,生成基于给定信息的实体类的对象。

package com.hh.model.factory;public class ShapeFactory {//使用 getShape 方法获取形状类型的对象public Shape getShape(String shapeType){if(shapeType == null){return null;}if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle();} else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle();} else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square();}return null;}
}

步骤 4:使用该工厂,通过传递类型信息来获取实体类的对象。

package com.hh.model.factory;public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();//获取 Circle 的对象,并调用它的 draw 方法Shape shape1 = shapeFactory.getShape("CIRCLE");//调用 Circle 的 draw 方法shape1.draw();//获取 Rectangle 的对象,并调用它的 draw 方法Shape shape2 = shapeFactory.getShape("RECTANGLE");//调用 Rectangle 的 draw 方法shape2.draw();//获取 Square 的对象,并调用它的 draw 方法Shape shape3 = shapeFactory.getShape("SQUARE");//调用 Square 的 draw 方法shape3.draw();}
}

步骤 5:执行程序,输出结果。

3、工厂方法模式

对简单工厂模式的改进,使用一个工厂接口,创建多个工厂类,每个工厂创建对应的对象。

工厂方法模式,创建一个工厂接口和创建多个工厂实现类,一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。有利于代码的维护和扩展。


手机接口类:

package com.hh.model.factory;public interface Phone {public void call();
}

两个手机实现类:

package com.hh.model.factory;public class IPhone implements Phone{@Overridepublic void call() {System.out.println("用苹果手机打电话!");}
}
package com.hh.model.factory;public class MPhone implements Phone{@Overridepublic void call() {System.out.println("用小米手机打电话!");}
}

工厂接口:

package com.hh.model.factory;public interface PhoneFactory {public Phone create();
}

小米手机工厂:

package com.hh.model.factory;public class MPhoneFactory implements PhoneFactory{@Overridepublic Phone create() {return new MPhone();}
}

苹果手机工厂:

package com.hh.model.factory;public class IPhoneFactory implements PhoneFactory{@Overridepublic Phone create() {return new IPhone();}
}

测试类:

package com.hh.model.factory;import org.testng.annotations.Test;public class FactoryPatternDemo {@Testpublic void test2() {// 生产小米手机PhoneFactory factory1 = new MPhoneFactory();factory1.create().call();// 生产苹果手机PhoneFactory factory2 = new IPhoneFactory();factory2.create().call();}}

运行结果:

4、抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。

应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。

实现:

我们将创建 ShapeColor 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactoryColorFactory,这两个工厂类都是扩展了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer

AbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 ShapeCIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 ColorRED / GREEN / BLUE),以便获取它所需对象的类型。

步骤 1:创建一个接口。

package com.hh.model.factory;public interface Shape {void draw();
}

步骤 2:创建实现接口的实体类。

package com.hh.model.factory;public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}
package com.hh.model.factory;public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}
package com.hh.model.factory;public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

步骤 3:创建一个接口。

public interface Color {void fill();
}

步骤 4:创建实现接口的实体类。

package com.hh.model.factory;public class Blue implements Color {@Overridepublic void fill() {System.out.println("Inside Blue::fill() method.");}
}
package com.hh.model.factory;public class Green implements Color {@Overridepublic void fill() {System.out.println("Inside Green::fill() method.");}
}
package com.hh.model.factory;public class Red implements Color {@Overridepublic void fill() {System.out.println("Inside Red::fill() method.");}
}

步骤 5:为 Color 和 Shape 对象创建抽象类来获取工厂。

package com.hh.model.factory;public abstract class AbstractFactory {public abstract Color getColor(String color);public abstract Shape getShape(String shape);
}

步骤 6:创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。

package com.hh.model.factory;public class ShapeFactory2 extends AbstractFactory {@Overridepublic Shape getShape(String shapeType){if(shapeType == null){return null;}if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle();} else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle();} else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square();}return null;}@Overridepublic Color getColor(String color) {return null;}
}
package com.hh.model.factory;public class ColorFactory extends AbstractFactory {@Overridepublic Shape getShape(String shapeType){return null;}@Overridepublic Color getColor(String color) {if(color == null){return null;}if(color.equalsIgnoreCase("RED")){return new Red();} else if(color.equalsIgnoreCase("GREEN")){return new Green();} else if(color.equalsIgnoreCase("BLUE")){return new Blue();}return null;}
}

步骤 7:创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。

package com.hh.model.factory;public class FactoryProducer {public static AbstractFactory getFactory(String choice){if(choice.equalsIgnoreCase("SHAPE")){return new ShapeFactory2();} else if(choice.equalsIgnoreCase("COLOR")){return new ColorFactory();}return null;}
}

步骤 8:使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象。

package com.hh.model.factory;import org.testng.annotations.Test;public class FactoryPatternDemo {@Testpublic void test3() {//获取形状工厂AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");//获取形状为 Circle 的对象Shape shape1 = shapeFactory.getShape("CIRCLE");//调用 Circle 的 draw 方法shape1.draw();//获取形状为 Rectangle 的对象Shape shape2 = shapeFactory.getShape("RECTANGLE");//调用 Rectangle 的 draw 方法shape2.draw();//获取形状为 Square 的对象Shape shape3 = shapeFactory.getShape("SQUARE");//调用 Square 的 draw 方法shape3.draw();//获取颜色工厂AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");//获取颜色为 Red 的对象Color color1 = colorFactory.getColor("RED");//调用 Red 的 fill 方法color1.fill();//获取颜色为 Green 的对象Color color2 = colorFactory.getColor("GREEN");//调用 Green 的 fill 方法color2.fill();//获取颜色为 Blue 的对象Color color3 = colorFactory.getColor("BLUE");//调用 Blue 的 fill 方法color3.fill();}@Testpublic void test2() {// 生产小米手机PhoneFactory factory1 = new MPhoneFactory();factory1.create().call();// 生产苹果手机PhoneFactory factory2 = new IPhoneFactory();factory2.create().call();}}

步骤 9:执行程序,输出结果。

参考链接1:抽象工厂模式 | 菜鸟教程

参考链接2:java工厂模式:简单工厂、工厂方法、抽象工厂(通俗易懂)_简单工厂模式,工厂方法模式,抽象工厂模式 java-CSDN博客


 

本文为学习笔记,所参考文章均已附上链接,若有疑问请私信!

创作不易,如果对你有点帮助的话麻烦点个赞支持一下!

新手小白,欢迎留言指正!

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

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

相关文章

python与上位机开发day04

模块和包、异常、PyQt5 一、模块和包 1.1 模块 Python中模块就是一个.py文件,模块中可以定义函数,变量,类。模块可以被其他模块引用 1.1.1 导入模块 """ 导入格式1: import 模块名 使用格式: …

【yolov8目标检测部署】TensorRT int8量化

原作者github:https://github.com/xuanandsix/Tensorrt-int8-quantization-pipline/tree/main 改进: 源代码支持的TensorRT版本为7.许多属性已经弃用; 在原有的代码上将支持的TensorRT版本从7改到8. !!不知道如何安装T…

速盾:海外服务器如何加速

海外服务器加速是一种优化网络连接的方法,目的是提高用户对海外服务器的访问速度。由于地理位置、网络带宽等因素的限制,用户在访问海外服务器时常常会遇到访问缓慢的问题。为了解决这个问题,以下是一些常见的海外服务器加速方法。 使用CDN技…

【设计模式】简单工厂模式(Simple Factory Pattern)

工厂模式(Factory Pattern) 用于创建不同类型的奖品对象。您可以创建一个奖品工厂,根据配置的类型来实例化相应的奖品对象。 public interface Prize {void award(); }public class MoneyPrize implements Prize {Overridepublic void awar…

(Askchat.ai、ChatAI、智友AI、AI写作生成器助手、在线AI助手)分享好用的ChatGPT

目录 1、Askchat.ai - 梦想为蓝图,ChatGPT为笔。 2、ChatAI 3、智友AI - MyChatGPT 4、AI写作生成器助手

opencv-基本操作

本篇文章,我们将聊一聊利用opencv进行的一些基本操作,以便后续我们利用opencv进行更加复杂的处理。 1、图像的读取、显示与保存 opencv中利用cv2.imread读取RGB图像,利用cv2.imshow() 进行图像的显示。 # 注意: cv2.imread读取RGB图像时, 返回…

在 Windows 系统上安装 TeamViewer 13

在 Windows 系统上安装 TeamViewer 13 References 默认安装到所有用户 同意协议 安装目录 勾选内容 打开文件位置 打开 rClientID.exe Extras -> Options -> Advanced Show advanced options -> Display language 重新启动TeamViewer 语言可修改为中文简体 …

稳扎稳打 部署丝滑 开源即时通讯(IM)项目OpenIM源码部署流程(linux windows mac)

背景 OpenIM包含多个关键组件,每个都是系统功能必不可少的一部分。具体来说,MongoDB 用于持久化存储;Redis 用作缓存;Kafka 用于消息队列;Zookeeper 用于服务发现;Minio 用于对象存储。这些组件的众多可能会…

C++14之std::exchange的使用和原理分析

目录 1.概述 2.使用 2.1.交换操作 2.2.移动语义 3.原理 4.综合示例 5.总结 1.概述 std::exchange 是 C 标准库中的一个实用函数,它的主要作用是替换一个对象的值,并返回该对象的旧值。这个函数在 C14 中引入,主要用于简化和优化代码。…

OpenCV如何在图像中寻找轮廓

返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV如何模板匹配 下一篇 :OpenCV系列文章目录(持续更新中......) 目标 在本教程中,您将学习如何: 使用 OpenCV 函数 cv::findContour…

第二弹:走进CSS世界,学习记录

目录 1.1. 了解CSS 1.2. 放置CSS的几种方式 1.3. CSS选择器 1.3.1. 基本选择器 1.3.2. 层级选择器 1.3.3. 属性选择器 1.3.4. 结构性伪类选择器 1.3.5. 状态伪类选择器 1.3.6. 选择器优先级 1.3.7. 文本属性 1.3.8. 背景属性 1.3.9. 尺寸属性 1.3.10. 列表属性 1…

K8s(二十三):Pod的生命周期详解

🔴 K8s(二十三):Pod的生命周期详解 1、Pod的生命周期1.1、Pod的创建1.2、Pod的调度1.3、Pod的初始化1.4、Pod的运行及钩子函数1.4.1 k8s中的3种钩子函数1.4.2 k8s中的3种探测类型1.5、Pod的终止1.6、Pod的重启2、Pod的生命周期的五种状态(相位)💖The Begin💖点点关注…

55.基于SpringBoot + Vue实现的前后端分离-旅游管理系统(项目 + 论文)

项目介绍 本站是一个B/S模式系统,采用SpringBoot Vue框架,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得基于SpringBoot Vue技术的旅游管理系统设计与实现管理工作系统…

ChatGPT: 人工智能对话的革命

介绍: 在人工智能领域,ChatGPT被视为创新的典范,重新定义了我们与技术交互的方式。从回答查询到生成创意内容,ChatGPT利用语言的力量促进了无缝沟通。在这篇全面指南中,我们深入探讨ChatGPT的复杂性,探索其功能、应用…

Java调用GDAL实现postgresql数据生成shp和dxf

需求 由于shp数据存储到postgresql数据库中,前端调用数据库实现数据的渲染,最近有一个新的需求,前端圈选数据,实现数据的下载,数据可以是shp、dxf、excel格式,这里主要记录在后端通过调用gdal来实现这个需…

使用STM32CubeMX对STM32F4进行串口配置

目录 1. 配置1.1 Pin脚1.2 RCC开启外部晶振1.3 时钟1.4 串口配置 2. 代码2.1 默认生成代码2.1 开启串口中断函数2.3 接收中断2.4 接收回调函数2.5 增加Printf 的使用 1. 配置 1.1 Pin脚 1.2 RCC开启外部晶振 1.3 时钟 外部使用8MHz晶振 开启内部16MHz晶振 使用锁相环 开启最高…

ROS2 学习笔记(二)常用小工具

1. rqt_console #启动 ros2 run rqt_console rqt_console日志级别&#xff1a;Fatal --> Error --> Warn --> Info --> Debug #修改允许发布的日志级别 ros2 run <package_name> <executable_name> --ros-args --log-level WARN2. launch文件 ROS2中…

Outlook大附件插件 有效解决附件大小限制问题

很多企业都是使用Outlook来进行邮件的收发&#xff0c;可是由于附件大小有限&#xff0c;导致很多大文件发不出去&#xff0c;就会产生Outlook大附件插件这种业务需求。 邮件系统在发送大文件时面临的限制问题主要如下&#xff1a; 1、附件大小限制&#xff1a;大多数邮件服务…

【MySQL】如何在MySQL中编写循环

是谁的心啊 孤单地留下 他还好吗 我多想爱他 那永恒的泪 凝固那一句话 也许可能蒸发 是谁的爱啊 比泪水坚强 轻声呼唤 就让我融化 每一滴雨水 演化成我翅膀 向着我爱的人 追吧 &#x1f3b5; 飞儿乐团《月牙湾》 MySQL中的循环通常在存储过程中使用&#…

基于Pytorch深度学习——Softmax回归

本文章来源于对李沐动手深度学习代码以及原理的理解&#xff0c;并且由于李沐老师的代码能力很强&#xff0c;以及视频中讲解代码的部分较少&#xff0c;所以这里将代码进行尽量逐行详细解释 并且由于pytorch的语法有些小伙伴可能并不熟悉&#xff0c;所以我们会采用逐行解释小…