设计模式-工厂方法模式

2023-11-02

前言

当我们面临需要创建不同类型对象的需求时,通常会使用工厂方法模式。工厂方法模式是一种创建型设计模式,它提供了一种将对象的创建与使用分离的方法,允许我们在不修改现有代码的情况下扩展系统以支持新类型的对象。

在本文中,我们将深入探讨工厂方法模式的原理,并使用Java代码示例来说明它的实现。

工厂方法模式概述

工厂方法模式是一种"创建者"模式,它在设计中引入了一个抽象工厂接口,由具体工厂类来实现该接口以创建具体产品。这种模式的核心思想是将对象的创建委托给子类,以便在运行时决定要创建的对象类型。

主要角色包括:

  1. 抽象产品(Product):定义了产品的接口,是具体产品类的共同基类。
  2. 具体产品(ConcreteProduct):实现了抽象产品接口,定义了具体产品的特性。
  3. 抽象工厂(Factory):定义了创建产品的工厂接口,包含一个工厂方法用于创建产品。
  4. 具体工厂(ConcreteFactory):实现了抽象工厂接口,负责创建具体产品的对象。

使用场景

工厂方法模式适用于以下场景:

  1. 需要创建多种类型的对象:当一个系统需要创建多个不同类型的对象,而这些对象都实现了同一个接口或继承自同一个基类时,可以考虑使用工厂方法模式。这样可以使得系统更加灵活,能够轻松地扩展或替换不同类型的对象。

  2. 延迟对象的创建:工厂方法模式将对象的创建延迟到子类中,这意味着在运行时才决定具体要创建哪个对象。这种方式有助于避免在客户端代码中硬编码具体类的实例化,从而提高了代码的可维护性和可扩展性。

  3. 遵循单一职责原则:工厂方法模式有助于确保每个具体工厂只负责创建一种具体产品,这符合单一职责原则,使得每个工厂类的职责清晰明确,易于维护和扩展。

  4. 需要解耦合:工厂方法模式可以帮助减少客户端与具体产品类之间的耦合度,因为客户端只依赖于抽象工厂和产品接口,而不直接依赖于具体产品类。这种解耦合有助于降低代码的复杂性和依赖关系。

  5. 支持多种产品变种:如果需要创建一组相关但有不同变种的产品,工厂方法模式也很有用。每个具体工厂可以负责创建特定变种的产品,以满足不同的需求。

  6. 测试和单元测试:工厂方法模式使得在单元测试中更容易模拟对象的创建过程,因为可以通过创建模拟工厂来创建模拟对象,从而使测试更容易进行。

总之,工厂方法模式适用于需要创建多种类型对象,需要延迟对象创建,需要解耦合的情况下。它是一种强大的设计模式,可提高系统的灵活性、可维护性和可扩展性。但是,如果只有少量的对象需要创建,并且它们之间的差异很小,可能不需要引入工厂方法模式,而可以使用简单的直接实例化对象的方式。

工厂方法模式优缺点

工厂方法模式是一种常用的设计模式,用于创建对象,它将对象的创建过程封装在工厂类中,客户端代码通过调用工厂方法来创建对象,而不需要直接实例化具体的对象类。这种模式有一些优点和缺点,下面是它们的主要特点:

优点:

  1. 松耦合: 工厂方法模式实现了客户端与具体产品类之间的松耦合,客户端代码只需要依赖于抽象工厂接口和抽象产品接口,而不需要依赖于具体的产品类,这使得系统更加灵活,易于维护和扩展。

  2. 可扩展性: 添加新的产品类非常容易,只需要创建一个新的具体产品类和相应的工厂类即可,不需要修改现有的客户端代码,符合开闭原则。

  3. 单一职责原则: 每个具体工厂类负责创建一种具体产品,符合单一职责原则,代码更加清晰和可维护。

  4. 封装复杂的对象创建过程: 如果创建一个对象需要复杂的初始化过程或者依赖于其他对象,工厂方法可以将这些复杂的创建逻辑封装在工厂类中,使客户端代码更加简洁。

缺点:

  1. 类的数量增加: 使用工厂方法模式会引入额外的工厂类,如果产品类很多,可能会导致类的数量大幅增加,增加了系统的复杂性。

  2. 每个产品都需要一个具体工厂类: 每个具体产品都需要对应一个具体工厂类,这可能会导致类的数量激增,增加了代码的维护难度。

  3. 增加了系统的抽象性: 工厂方法模式引入了抽象工厂和抽象产品,使得系统更加抽象,对于一些简单的情况可能会显得繁琐。

  4. 不适合小规模应用: 如果一个应用程序只有很少的产品类和不需要频繁添加新产品,使用工厂方法模式可能会显得过于复杂,不划算。

总之,工厂方法模式在需要创建多种具体产品对象的情况下,提供了一种灵活、可扩展、可维护的解决方案,但需要根据具体的应用场景和需求来选择是否使用。

Java代码示例

假设我们有一个文档编辑器,需要创建不同类型的文档对象,如PDF文档和Word文档。首先,我们定义产品接口和具体产品类:

// 抽象产品
interface Document {
    void open();
    void close();
}

// 具体产品 - PDF文档
class PDFDocument implements Document {
    @Override
    public void open() {
        System.out.println("打开PDF文档");
    }

    @Override
    public void close() {
        System.out.println("关闭PDF文档");
    }
}

// 具体产品 - Word文档
class WordDocument implements Document {
    @Override
    public void open() {
        System.out.println("打开Word文档");
    }

    @Override
    public void close() {
        System.out.println("关闭Word文档");
    }
}

接下来,我们定义抽象工厂和具体工厂类:

// 抽象工厂
interface DocumentFactory {
    Document createDocument();
}

// 具体工厂 - PDF文档工厂
class PDFDocumentFactory implements DocumentFactory {
    @Override
    public Document createDocument() {
        return new PDFDocument();
    }
}

// 具体工厂 - Word文档工厂
class WordDocumentFactory implements DocumentFactory {
    @Override
    public Document createDocument() {
        return new WordDocument();
    }
}

现在,我们可以使用工厂方法模式来创建文档对象:

public class Main {
    public static void main(String[] args) {
        // 创建PDF文档工厂
        DocumentFactory pdfFactory = new PDFDocumentFactory();
        // 创建PDF文档
        Document pdfDocument = pdfFactory.createDocument();
        pdfDocument.open();
        pdfDocument.close();

        // 创建Word文档工厂
        DocumentFactory wordFactory = new WordDocumentFactory();
        // 创建Word文档
        Document wordDocument = wordFactory.createDocument();
        wordDocument.open();
        wordDocument.close();
    }
}

运行上述代码,你将看到输出:

打开PDF文档
关闭PDF文档
打开Word文档
关闭Word文档

这个示例展示了工厂方法模式的核心思想:不同的工厂创建不同类型的产品,客户端代码通过工厂接口来获取产品对象,而无需关心具体产品的创建过程。

工厂方法模式使系统更加灵活,能够轻松添加新的产品类型,同时保持了高内聚和低耦合的设计原则,是面向对象设计中常用的一种模式。

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

设计模式-工厂方法模式 的相关文章

随机推荐

  • 有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?

    Apple 算是最重视应用开发体验的公司了 从Xib到StoryBoard 从Auto Layout到Size Class 每一次的更新 都会给iOS应用的开发带来不小的便利 但是 对于绝对多数iOS攻城狮来说 我们依然还是很害怕写UITa
  • 解决docker pull 很慢的问题

    再docker拉取镜像时 花费时间太长 用如下方法可以解决 root localhost mkdir p etc docker root localhost cat etc docker daemon json registry mirro
  • mysql Undo Tablespaces

    分离 undo 表空间相关的参数 innodb undo directory 指定单独存放 undo 表空间的目录 默认为 即 datadir 可以设置相对路径或者绝对路径 该参数实例初始化之后虽然不可直接改动 但是可 以通过先停库 修改配
  • 联想工作站光盘或WinPE重装Win7找不到SSD和另外一个2T磁盘

    工作站比较老了 苏州重启系统修了 应该是原来的SSD硬盘损坏 修复工具无法修复 只能重装了 由于某一应用软件要求 只能装Win7系统 使用老毛桃制作的WinPE进去看了分区 安装系统时无法找到新的SSD盘和之前的2T磁盘
  • PLC的通信模式

    说到PLC的通讯模式 主要有两种 一种是并行通讯模式 一种是串行通讯模式 这两种通信模式有什么区别呢 PLC串行通信 串行通信一般是用二进制的位 BIT 为单位的数据传输方式 每次都只传送一位 然后除了地线之外 在一个数据传输方向上面只要一
  • element tree树形结构接口不支持搜索、懒加载情况下实现搜索

    目前项目中 element tree树形结构由于数据太多使用了懒加载 并且接口不支持搜索 只能由前端实现搜索功能 暂时按照自己思路实现功能 思路为 输入搜索内容后 直接遍历树形结构的数据 通过filter筛选出结果之后再赋值给树形结构 de
  • matlab径向分布函数作图_分子动力学的径向分布函数绘制

    这是过冷水之前在工作中的一张图片 这张图片的实际含义是以坐标原点为参考点 距离原点距离x处的小球个数f x 分布图 这个问题理解起来好容易 统计距离和小球个数的关系 but实际问题是过冷水要处理的是这样的问题 请问请告诉我随意找一个小球为原
  • 小团队管理核心(一)

    主管应该投身具体业务还是专注于管理 投身业务 or 专注管理 主管应该投身具体业务还是专注于管理 一 主管的定位 二 如何实现老板目标 三 主管应当专注管理 一 主管的定位 定位简述 通过下属实现经营者目标的人 定位解析 由此看来我们的目标
  • ThreeJS第一人称视角处理

    简介 第一人称控件指针锁定API允许您在游戏界面中锁定鼠标或其他指针设备 以便您不用绝对定位光标就可以获得坐标变化值 从而准确地判断用户正在做什么 并且还可以防止用户意外地进入另一块屏幕或别的什么地方 从而导致误操作 在ThreeJs中实现
  • Python 查看数据类型与格式

    一般我们拿到一个数据 会先看一下这个数据有多少行多少列 各个字段是什么 数据格式类型是什么 在开始讲数据格式前 需要先梳理一下各个数据类型 我们常使用的库一般是numpy和pandas Numpy下的核心是数组 array ndarray
  • Redis支持哪几种数据类型?

    Redis支持哪几种数据类型 1 什么是Redis 2 优缺点 3 Redis相比Memcached有哪些优势 4 Redis支持的数据类型 4 1 String 字符串 4 2 List 列表 4 3 Set 集合 4 4 Sorted
  • HTTPS原理(证书验证+数据传输)

    HTTPS协议相关的概念有SSL 非对称加密 CA证书等 为什么用了HTTPS就是安全的 HTTPS底层原理如何实现 用了HTTPS就一定安全吗 HTTPS实现原理 HTTPS在内容传输上的加密使用的是对称加密 证书验证阶段使用非对称加密
  • 图像评价指标(python)

    图像评价指标的综合记录 一 信息熵 熵是衡量图像中所包含的信息量的大小 熵越大说明包含的信息越多 意味着可以从处理后的图像中获取更多的信息 用信息熵来计算图像的熵值 代码 import cv2 import numpy as np impo
  • C 标准库 - 《stdio.h》

    原文链接 https www runoob com cprogramming c standard library stdio h html 简介 stdio h 头文件定义了三个变量类型 一些宏和各种函数来执行输入和输出 库变量 下面是头
  • 前端页面间数据传递常用的几种方式

    1 常用方式 url页面路径携带参数传递 localStorage方式传递 sessionStorage方式传递 cookie的方式传递 2 方式对比 url字节限制可以参考这一篇文章 HTTP中的URL长度限制 其中cookie的setC
  • 开关电源的时钟倍频 辐射发射超标RE+ 噪声源+干扰原因

    1 收藏 史上最全开关电源传导与辐射超标整改方案 医疗设备低频30 50Mhz超标 2 https bbs elecfans com m jishu 941580 1 1 html 3 辐射噪声的产生机理 知乎 1 电流源 噪声源 2 天线
  • 【华为OD机试】叠积木(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • 傅里叶变换快速入门

    网上关于傅里叶变换的解释特别多 但大部分都比较偏理论 导致我看来N多教程也还是懵懵懂懂 在某本书 信号完整性分析 中看到一句震耳发聩的话 每个工程师都应该亲自动手计算一遍傅里叶变换 我知道很多工具可以直接给出傅里叶变换结果 但不清不楚一直是
  • 修改UGF官方的starForce为自己所用

    第一步 修改Launcher的名字 比如我这里是修改成SpaceShoot 第二步修改命名空间名字 重新命名为SpaceShoot 第三步 重新设置Launcher场景中丢失的脚本 Builtin下JsonLite Localization
  • 设计模式-工厂方法模式

    文章目录 前言 工厂方法模式概述 使用场景 工厂方法模式优缺点 Java代码示例 前言 当我们面临需要创建不同类型对象的需求时 通常会使用工厂方法模式 工厂方法模式是一种创建型设计模式 它提供了一种将对象的创建与使用分离的方法 允许我们在不