工厂方法模式-Factory Method Pattern

2023-11-14

工厂方法模式-Factory Method Pattern

工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式

这是它的结构图:

在这里插入图片描述
它包含四个角色:

● Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。

● ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。

● Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。

● ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。

完整解决方案

开发人员决定使用工厂方法模式来设计日志记录器,其基本结构如图所示:

在这里插入图片描述

//日志记录器接口:抽象产品
   interface Logger {
   public void writeLog();
   }
   
   //数据库日志记录器:具体产品
   class DatabaseLogger implements Logger {
   public void writeLog() {
   System.out.println("数据库日志记录。");
   }
   }
   //文件日志记录器:具体产品
    class FileLogger implements Logger {
    public void writeLog() {
    System.out.println("文件日志记录。");
    }
    }
    //日志记录器工厂接口:抽象工厂
    interface LoggerFactory {
    public Logger createLogger();
    }
   //数据库日志记录器工厂类:具体工厂
    class DatabaseLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
    //连接数据库,代码省略
    //创建数据库日志记录器对象
    Logger logger = new DatabaseLogger();
    //初始化数据库日志记录器,代码省略
    return logger;
    }
    }
    //文件日志记录器工厂类:具体工厂
   class FileLoggerFactory implements LoggerFactory {
   public Logger createLogger() {
   //创建文件日志记录器对象
   Logger logger = new FileLogger();
   //创建文件,代码省略
   return logger;
   }
   }
   //客户端代码

class Client {
   public static void main(String args[]) {
   LoggerFactory factory;
   Logger logger;
   factory = new FileLoggerFactory(); //可引入配置文件实现
   logger = factory.createLogger();
   logger.writeLog();
   }
   }

我们可以通过Java的反射机制和xml完成创建工厂对象

先来个config.xml的代码

   <!— config.xml -->
   <?xml version="1.0"?>
   <config>
   <className>FileLoggerFactory</className>
   </config>

再来个xml读取工具类 XMLUtil

//工具类XMLUtil.java
   import javax.xml.parsers.*;
   import org.w3c.dom.*;
   import org.xml.sax.SAXException;
   import java.io.*;
  
   public class XMLUtil {
   //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
   public static Object getBean() {
    try {
    //创建DOM文档对象
    DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = dFactory.newDocumentBuilder();
    Document doc;
    doc = builder.parse(new File("config.xml"));
   
    //获取包含类名的文本节点
    NodeList nl = doc.getElementsByTagName("className");
    Node classNode=nl.item(0).getFirstChild();
    String cName=classNode.getNodeValue();
   
    //通过类名生成实例对象并将其返回
    Class c=Class.forName(cName);
    Object obj=c.newInstance();
    return obj;
    }
    catch(Exception e) {
    e.printStackTrace();
   return null;
    }
    }
    }

客户端代码如下:

class Client {
   public static void main(String args[]) {
   LoggerFactory factory;
   Logger logger;
   factory = (LoggerFactory)XMLUtil.getBean(); //getBean()的返回类型为Object,需要进行强制类型转换
   logger = factory.createLogger();
   logger.writeLog();
   }
   }

也可以直接向客户端隐藏了工厂的方法

在这里插入图片描述
工厂类把logger的创建内置:

//改为抽象类
   abstract class LoggerFactory {
   //在工厂类中直接调用日志记录器类的业务方法writeLog()
   public void writeLog() {
   Logger logger = this.createLogger();
   logger.writeLog();
   }
  
   public abstract Logger createLogger();
   }

工厂方法模式-Factory Method Pattern优缺点

优点:

(1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

(2) 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。

(3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

缺点:

(1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

(2) 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

工厂方法模式-Factory Method Pattern 的相关文章

  • 用于解析和构建逻辑表达式的 Java 库

    我正在寻找一个 Java 开源库来解析和构建类似 SQL 的表达式 例如评估表达式的有效性 例如 a x or y and b z 另外我想要一个用于构建或扩展表达式的 API 就像是 Expression exp new Expressi
  • java.lang.VerifyError:JVMVRFY012堆栈形状不一致;

    在 WAS 8 5 5 中部署 Maven 项目时出现以下错误 我在WAS中安装了JDK 1 6和1 7 错误500 org springframework web util NestedServletException 处理程序处理失败
  • 在 Java 正则表达式中获取多个模式的重叠匹配

    我有同样的问题这个链接 https stackoverflow com questions 18751486 matching one string multiple times using regex in java 但有多种模式 我的正
  • 对象数组的数组(二维数组)JNI

    我正在努力创建自定义对象类型 ShareStruct 的二维数组 jobjectArray ret jobjectArray ins jobjectArray outs jclass myClass env gt FindClass env
  • 使类只能从特定类实例化

    假设我有 3 节课class1 class2 and class3 我怎样才能拥有它class1只能通过实例化class2 class1 object new class1 但不是 class3 或任何其他类 我认为它应该与修饰符一起使用
  • 查询 MongoDB 集合中的字段。

    我正在尝试查询 mongodb 集合中的特定字段 这是我的代码和输出 Mongo m new Mongo DB db m getDB mydb DBCollection coll db getCollection student addin
  • Java 卡布局。多张卡中的一个组件

    一个组件 例如JLabel 在多张卡中使用CardLayout 目前看来该组件仅出现在它添加到的最后一张卡上 如果有办法做到这一点 我应该吗 这是不好的做法吗 或者有其他选择吗 你是对的 它只出现在 添加到的最后一张卡 中 但这与CardL
  • 本地开发的 Azure Functions 扩展包版本问题

    我有一个带有队列触发器的 Java 11 Azure 函数 该函数在部署到 Azure 时按预期工作 并正确从定义的服务总线主题中提取消息 但是 运行相同的功能locally除非我回滚版本 否则不起作用Azure Functions 绑定扩
  • 以有效的方式从 Map 中删除多个键?

    我有一个Map
  • 如何将 Java 地图转换为在 Scala 中使用?

    我正在开发一个 Scala 程序 该程序调用 Java 库中的函数 处理结果并生成 CSV 有问题的 Java 函数如下所示 Map
  • Java:SortedMap、TreeMap、可比较?如何使用?

    我有一个对象列表 需要根据其中一个字段的属性进行排序 我听说 SortedMap 和 Comparator 是实现此目的的最佳方法 我是否要与正在排序的类实现 Comparable 还是创建一个新类 如何实例化 SortedMap 并传入
  • 具有 JPA 持久性的 Spring 状态机 - 存储库使用

    我试图弄清楚如何轻松使用 Spring 状态机 包括使用 JPA 进行持久化 这是我正在处理的问题 不兼容的数据类型 工厂和持久性 在程序的某个时刻 我想使用连接到用户的状态机 有用于此目的的存储库 项目spring statemachin
  • 在尝试使用 GPS 之前如何检查 GPS 是否已启用

    我有以下代码 但效果不好 因为有时 GPS 需要很长时间 我该如何执行以下操作 检查GPS是否启用 如果启用了 GPS 请使用 GPS 否则请使用网络提供商 如果 GPS 时间超过 30 秒 请使用网络 我可以使用时间或 Thread sl
  • 生成 equals 和 hashcode 时忽略属性

    假设我有一个类 Customer public class Customer private String firstName private String lastName private String doNotAddMeToEqual
  • 在 Java 中创建 XML 文件的最佳方法是什么?

    我们目前使用 dom4j 来创建 XML 文件 不过 我猜现在有更好的东西了 如果我们使用的是 Java 1 6 或更高版本 那么在编写 XML 文件时最好使用什么类 运行速度最快 使用简单 我不需要构建一个 DOM 然后编写整个 DOM
  • javax.media.jai 类的公共下载?

    这是一个非常简单的问题 我一直在寻找可以下载 javax media jai 库的地方 我找到了 jai imageio 库 但是我发现的所有其他 jai 内容要么已经过时 2008 年及之前 然后我遇到了登录屏幕 是否有 javax me
  • Collections.sort(list) 和 list.sort(Comparator) 之间的区别

    有什么理由让我应该选择Collections sort list 方法而不是简单地调用list sort 内部Collections sort只是调用sort的方法List无论如何 上课 令人惊讶的是几乎每个人都告诉我使用Collectio
  • 受信任的 1.5 小程序可以执行系统命令吗?

    如果是的话 这个能力有什么限制吗 具体来说 我需要以 Mac OSX 为目标 我以前用过这个在 Windows 系统上启动东西 但从未在 Mac 上尝试过 public void launchScript String args Strin
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的
  • java中void的作用是什么?

    返回类型 方法返回值的数据类型 如果方法不返回值 则返回 void http download oracle com javase tutorial java javaOO methods html http download oracle

随机推荐

  • STM32使用串口(空闲中断IDLE+DMA)接收ESP8266数据

    串口空闲中断 ESP8266收发数据 一 在使用ESP8266模块时遇到的一些问题 首先是对模块数据的收发 我们在发送AT指令时会收到模块发送的反馈数据 在我们没有使用实时操作系统的情况下 通过HAL库的串口收发函数是比较难以完成工作的 我
  • aaa计费请求_什么是AAA(身份验证,授权和计费)?

    aaa计费请求 AAA or Authentication Authorization and Accounting is a term used to describe 3 functions in IT Mainly AAA is us
  • 导航样式

    鼠标滑过 bottom 黄线从中间展开到两边
  • NLP: 0基础应用T5模型进行文本翻译代码实例~

    文章目录 前言 一 目标文本是什么 二 模型调用步骤 1 引入库 2 导入模型 本文使用 t5 base 3 使用分词器对目标文本进行分词 4 对刚刚生成的分词结果进行目标语言的生成工作 5 对生成的目标语言进行解码工作 就可得到目标语言的
  • 一文读懂Matter协议的前世今生和未来

    从事Zigbee行业的应该都知道今年Zigbee联盟已经改名为CSA联盟 并推出一个全新的 定位于解决IOT碎片化的统一协议 即Matter协议 Matter协议的由来 Matter协议的前身CHIP Connected Home Over
  • 从一个数组中随机取出若干个数

    随机取数 下面给出从一个数组随机取出若干数字组成新书组和从一个数组随机取出一个数字的方法 代码如下 从一个数组中随机取出若干个元素组成数组 param Array arr 原数组 param Number count 需要随机取得个数 co
  • 如何确保事务提交后才执行异步操作

    参考博客TransactionSynchronizationManager和TransactionSynchronizationAdapter 场景 业务流程背景 对于 法律法规 法规库 标签管理 列表中的某一条数据 操作完标注和解析按钮后
  • Angular离线API文档安装指南

    需要的材料 nginx 官方angularjs zip 完整包 步骤 1 先上www angular org 下载个完整的zip包 2 到nginx 网站下载 nginx 3 修改 nginx 1 6 2 conf nginx conf 文
  • 利用win10自带的工具测硬盘读写速度

    利用win10自带的硬盘测试工具测读写速度 一 win q 打开搜索框 输入 cmd 找到命令提示符 右击以管理员身份运行 二 在命令框里输入 winsat disk 是默认测试系统盘的速度 不出意外都是C盘 三 当我们要想测试其他盘的时候
  • MySQL学习笔记——MySQL数据类型(拉勾教育数据分析实战训练营学习笔记)

    MySQL学习笔记 MySQL数据类型 MySQL数据库中 每一条数据都有其数据类型 主要可以分为数值型 字符串型和日期时间型三大类 说明如下所示 数值类型 TINYINT 一个非常小的整数 占1字节 如果是有符号 范围是 128 127
  • MFC窗口销毁过程

    MFC窗口销毁过程 考虑单窗口情况 假设自己通过new创建了一个窗口对象pWnd 然后pWnd gt Create 则销毁窗口的调用次序 1 手工调用pWnd gt DestroyWindow 2 DestroyWin
  • Elasticsearch实战-磁盘IO被打满

    背景 事情是这样的 一天下午4点42分左右 业务反馈我开发的服务在测试环境出现问题 返回资源数据是0 查日志发现是ES访问超时 相当于数据库挂了 持续了20多分钟自己恢复 咨询了ES团队 最终得到下面的答复 当前集群现状 1 当前集群数据I
  • python爬取研究生招生网招生信息

    import requests from bs4 import BeautifulSoup from pandas core frame import DataFrame import re import time class Gradua
  • Nginx惊群问题

    Nginx惊群问题 1 简介 简单来说 多线程 多进程 linux下线程进程也没有多大区别 等待同一个socket事件 当这个事件发生时 这些线程 进程被同时唤醒 就是惊群 可以想见 效率很低下 许多进程被内核重新调度唤醒 同时去响应这一个
  • 07.JavaWeb-Vue+elementUI

    1 Vue 功能替代JavaScript和jQuery 基于JavaScript实现的前端框架 1 1配置Vue 1 1 1引入vue库 方法一 通过cdn链接引入最新版本的vue 可能会慢些 方法二 将vue库下载到本地 通过相对路径引入
  • SpringFramework核心技术三:Spring的验证机制

    Spring验证 Spring 3引入了对其验证支持的几项增强 首先 现在完全支持JSR 303 Bean验证API 其次 当以编程方式使用时 Spring的DataBinder现在可以验证对象并绑定到它们 第三 Spring MVC现在支
  • 【已解决】容器镜像安装vim的踩坑之路

    一 背景 在部署 Elasticsearch 7 17 7 版本时 进入到改容器后 发现该镜像没有vi 同时使用apt也无法正常安装 于是百度找解决方案 一步一坑 最后完美解决 二 解决 首先进入镜像中 docker exec it es
  • springboot+mysql物流车辆管理系统-计算机设计源码84722

    摘要 由于数据库和数据仓库技术的快速发展 物流车辆管理系统建设越来越向模块化 智能化 自我服务和管理科学化的方向发展 物流车辆管理系统对处理对象和服务对象 自身的系统结构 处理能力 都将适应技术发展的要求发生重大的变化 物流车辆管理系统除了
  • 基于深度学习的智慧城市火灾检测方法

    1 文章信息 本次介绍的文章是在2022年发表在Electronics的一篇文章 文章题目为 Fire Detection Method in Smart CityEnvironments Using a Deep Learning Bas
  • 工厂方法模式-Factory Method Pattern

    工厂方法模式 Factory Method Pattern 工厂方法模式 Factory Method Pattern 定义一个用于创建对象的接口 让子类决定将哪一个类实例化 工厂方法模式让一个类的实例化延迟到其子类 工厂方法模式又简称为工