深入理解与应用工厂方法模式

news2024/9/25 19:17:55

文章目录

  • 一、模式概述
  • **二、适用场景**
  • **三、模式原理与实现**
  • **四、采用工厂方法模式的原因**
  • **五、优缺点分析**
  • **六、与抽象工厂模式的比较**
  • 总结

一、模式概述

​ 工厂方法模式是一种经典的设计模式,它遵循面向对象的设计原则,特别是“开闭原则”,通过定义一个用于创建对象的接口,将对象的实例化过程推迟到子类中实现。这种模式与抽象工厂模式类似,但更加专注于对单一接口下产品类型的创建。

二、适用场景

  • 复杂对象的创建需要大量重复代码时。
  • 对象创建依赖于外部资源或信息。
  • 需要统一管理对象生命周期,如会话、资源池对象等。
  • 需要隐藏对象的具体类型,提高代码的抽象层次。

以 MyBatis 的 LogFactory 类为例,展示了工厂方法模式如何应用于实际项目中,通过灵活的选择和初始化不同日志实现类(如 Slf4j、Log4j 等),达到按需创建和管理日志对象的目的。

三、模式原理与实现

​ 工厂方法模式的核心在于封装对象的创建过程,提高对象创建的可复用性。通过观察代码实现可知,核心工厂类并不直接创建具体产品,而是通过判断条件委派给子类,从而使得在不修改核心工厂的前提下能够引入新的产品实现。

工厂方法模式的核心组成部分包括:

在这里插入图片描述

  1. 抽象产品(Abstract Product):定义产品的公共接口,如 IProduct 接口。
  2. 核心工厂(Concrete Factory):如 ProductFactory 类,提供创建产品实例的通用接口,根据传入的参数决定创建何种具体产品。
  3. 具体产品(Concrete Products):如 Product_A_ImplProduct_B_Impl 类,它们实现抽象产品接口,提供了具体产品的实例化过程。

以下是工厂方法模式的一个详细代码示例,创建一个动物工厂,它可以创建各种类型的动物对象:

首先,我们定义一个抽象的动物接口(抽象产品):

// 抽象产品
public interface Animal {
    void makeSound();
}

然后,我们创建几个实现了 Animal 接口的具体动物类(具体产品):

// 具体产品:Dog 类
public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof! Woof!");
    }
}

// 具体产品:Cat 类
public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow! Meow!");
    }
}

接下来,我们定义一个抽象工厂类,它声明了一个创建动物对象的方法:

// 抽象工厂
public abstract class AnimalFactory {
    public abstract Animal createAnimal(String animalType);
}

然后,我们创建两个具体工厂类,它们实现了上述抽象工厂类,并在其中定义了如何创建具体动物对象:

// 具体工厂:DogFactory 类
public class DogFactory extends AnimalFactory {
    @Override
    public Animal createAnimal(String animalType) {
        if ("dog".equalsIgnoreCase(animalType)) {
            return new Dog();
        }
        throw new IllegalArgumentException("Invalid animal type");
    }
}

// 具体工厂:CatFactory 类
public class CatFactory extends AnimalFactory {
    @Override
    public Animal createAnimal(String animalType) {
        if ("cat".equalsIgnoreCase(animalType)) {
            return new Cat();
        }
        throw new IllegalArgumentException("Invalid animal type");
    }
}

最后,我们通过客户端代码来演示如何使用工厂方法模式创建并使用动物对象:

public class Client {
    public static void main(String[] args) {
        // 使用 DogFactory 创建 Dog 对象
        AnimalFactory dogFactory = new DogFactory();
        Animal dog = dogFactory.createAnimal("dog");
        dog.makeSound();  // 输出:Woof! Woof!

        // 使用 CatFactory 创建 Cat 对象
        AnimalFactory catFactory = new CatFactory();
        Animal cat = catFactory.createAnimal("cat");
        cat.makeSound();  // 输出:Meow! Meow!
    }
}

测试结果

在这里插入图片描述

​ 在这个示例中,AnimalFactory 是抽象工厂,DogFactoryCatFactory 是具体工厂,DogCat 是具体产品。客户端代码通过工厂方法来获取具体产品,而无需直接创建产品对象,这样就实现了对象的创建和使用相分离,同时也易于扩展新的产品类型。

四、采用工厂方法模式的原因

  1. 分离对象创建与使用:降低耦合性,增强代码的可维护性与可扩展性。
  2. 减少重复代码:通过工厂类集中处理相似对象的创建逻辑,避免代码冗余。
  3. 管理创建逻辑的变化:当业务逻辑发生变化时,只需修改工厂类的实现,无需改动大量调用处。

五、优缺点分析

  • 优点:支持灵活定制,隐藏实现细节,符合开闭原则,实现多态性。
  • 缺点:当抽象接口新增方法时,可能导致所有具体工厂都要相应修改;若具体工厂实现逻辑各异,则增加代码理解和维护难度。

六、与抽象工厂模式的比较

​ 尽管工厂方法模式与抽象工厂模式都属于创建型设计模式,但前者更关注于单一接口下产品的创建与替换,强调继承结构的连续性;而后者聚焦于一组相关产品间的协同创建,更看重组合的扩展性,两种模式在实际应用中各有侧重。

总结

​ 工厂方法模式以其简洁的实现和良好的扩展性,在实际项目中广泛使用。在面临对象创建逻辑较为复杂或需要灵活切换产品实现时,它是一种值得考虑的设计解决方案。然而,在简单对象创建场景下,开发者需审慎使用,避免因过度设计引入额外复杂性。

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

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

相关文章

一文扫盲:室内导航系统的应用场景和技术实现(入门级)

hello,我是贝格前端工场,之间搞过一些室内导航项目,有2D也有3D的,算是有些经验,这里给大家分享一下室内导航的基本尝试,欢迎老铁们点赞、关注,如有需求可以私信我们。 一、室内导航是什么 室内…

vs报错1168链接错误——关于:LNK1168 无法打开 E:\VS\文件名\x64\Debug\文件名. 进行写入问题的解决方法

关于这个问题我在网上找了一些方法。 有些方法解决了这个问题, 但是有点麻烦, 有些方法可能不能解决问题。 这里我先把我在网上找到的方法写出来: 第一种方法是可能开着一个程序,就是这个终端。有的时候报错1168是因为你没有关这…

Vue中如何实现动态路由?

在前端开发中,Vue.js 是一个极为流行的 JavaScript 框架,提供了灵活性和易用性,使得开发者可以快速构建单页面应用(SPA)。在 Vue 中,我们经常需要处理动态路由的情况,比如根据用户的操作或者权限…

设计模式 (四) -简单工厂模式

请直接看原文:设计模式(四)简单工厂模式 | BATcoder - 刘望舒 (liuwangshu.cn) --------------------------------------------------------------------------------------------------------------------------- 1.简单工厂模式简介 定义 简单工厂…

chrome选项页面options page配置

options 页面用以定制Chrome浏览器扩展程序的运行参数。 通过Chrome 浏览器的“工具 ->更多工具->扩展程序”,打开chrome://extensions页面,可以看到有的Google Chrome扩展程序有“选项Options”链接,如下图所示。单击“选项Options”…

Go-知识struct

Go-知识struct 1. struct 的定义1.1 定义字段1.2 定义方法 2. struct的复用3. 方法受体4. 字段标签4.1 Tag是Struct的一部分4.2 Tag 的约定4.3 Tag 的获取 githupio地址:https://a18792721831.github.io/ 1. struct 的定义 Go 语言的struct与Java中的class类似&am…

简单的input框输入竟然异常卡顿,一个日常性能问题的排查思路

我们公司产品主要提供企业项目管理服务,那么自然有配套的desk工单管理系统,用于搜集客户bug以及相关问题反馈。有一天我在测试功能时碰巧发现了一个bug,所以就想着提一个工单记录下方便日后修复。但就在创建工单填写标题时我发现标题输入卡爆…

2. vue 工程创建

1. 基于 vite创建 官方文档: https://v3.cn.vuejs.org/guide/installation.html#vite vite官网: https://vitejs.cn 使用vite创建的优势: 开发环境中,无需打包操作,可快速的冷启动。轻量快速的热重载(HMR)。真正的按需编译,不再…

深度学习-Softmax 回归 + 损失函数 + 图片分类数据集

Softmax 回归 损失函数 图片分类数据集 1 softmax2 损失函数1均方L1LossHuber Loss 3 图像分类数据集4 softmax回归的从零开始实现 1 softmax Softmax是一个常用于机器学习和深度学习中的激活函数。它通常用于多分类问题,将一个实数向量转换为概率分布。Softmax函…

如何提取图片中某个位置颜色的RGB值,RGB十进制值与十六进制的转换

打开本地的画图工具,把图片复制或截图粘进去,用颜色提取器点对应的位置就可以提取了。 获取到的 RGB 值为 (66,133,244) 转化后的值为 #4285F4。 【内容拓展一】:RGB 十进制值与十六进制的转换 当我们从 RGB 十进制值转换为十六进制值时&a…

YOLOv应用开发与实现

一、背景与简介 YOLO(You Only Look Once)是一种流行的实时目标检测系统,其核心思想是将目标检测视为回归问题,从而可以在单个网络中进行端到端的训练。YOLOv作为该系列的最新版本,带来了更高的检测精度和更快的处理速…

LeetCode 刷题 [C++] 第215题.数组中的第K个最大元素

题目描述 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 题目分析 根据题意分析&…

巧【二叉搜索树的最近公共祖先】【二叉搜索树的性质】Leetcode 235. 二叉搜索树的最近公共祖先

【二叉搜索树的最近公共祖先】【二叉搜索树性质】Leetcode 235. 二叉搜索树的最近公共祖先 【巧】解法1 利用二叉搜索树有序的性质解法2 采用二叉树求最近公共祖先的方法——后序遍历 ---------------🎈🎈235. 二叉搜索树的最近公共祖先 题目链接&#x…

论文阅读-高效构建检查点

论文标题:On Efficient Constructions of Checkpoints 摘要 高效构建检查点/快照是训练和诊断深度学习模型的关键工具。在本文中,我们提出了一种适用于检查点构建的有损压缩方案(称为LC-Checkpoint)。LC-Checkpoint同时最大化了…

vue中scss样式污染引发的思考

新做了一个项目,就是在登录后,就会产生左侧菜单的按钮颜色不一样。 然后发现样式是从这里传过来的 发现是登录页面的css给污染了 就是加了scope就把这个问题解决了 然后想总结一下这个思路:就是如何排查污染样式: 如果出现了…

微信小程序开启横屏调试

我们先打开小程序项目 开启真机运行 目前是一个竖屏的 然后打开全局配置文件 app.json 给下面的 window 对象 下面加一个 pageOrientation 属性 值为 landscape 运行结果如下 然后 我们开启真机运行 此时 就变成了个横屏的效果

[vue error] TypeError: AutoImportis not a function

问题详情 问题描述: element plus按需导入后,启动项目报错: 问题解决 将unplugin-auto-import 回退到0.16.1 npm install unplugin-auto-import0.16.1 安装完后再次运行就好了

牛客周赛 Round 35 解题报告 | 珂学家 | 构造 + 组合数学

牛客周赛 Round 35 解题报告 | 珂学家 | 构造 组合数学 前言 整体评价 F/G是数学题,E是一道有趣的构造题, 需要一点点空间想象力,其他几题也不错。不过整场被python的库函数,折磨得崩溃,T_T. A. 小红的字符串切割 题型: 签到 …

IO多路复用:提高网络应用性能的利器

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【比较mybatis、lazy、sqltoy、lambda、操作数据 】操作批量新增、分页查询【一】

orm框架使用Lambda性能比较 环境: idea jdk17 spring boot 3.0.7 mysql 8.0测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本mybatis☑️☑️3.5.4sqltoy☑️☑️5.2.98lazy✖️☑️1.2.3-JDK17 数据库表(含有唯一性索引s_u) CREATE TABLE sys_u…