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

文章目录

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

一、模式概述

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

二、适用场景

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

以 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 {@Overridepublic void makeSound() {System.out.println("Woof! Woof!");}
}// 具体产品:Cat 类
public class Cat implements Animal {@Overridepublic void makeSound() {System.out.println("Meow! Meow!");}
}

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

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

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

// 具体工厂:DogFactory 类
public class DogFactory extends AnimalFactory {@Overridepublic Animal createAnimal(String animalType) {if ("dog".equalsIgnoreCase(animalType)) {return new Dog();}throw new IllegalArgumentException("Invalid animal type");}
}// 具体工厂:CatFactory 类
public class CatFactory extends AnimalFactory {@Overridepublic 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.hqwc.cn/news/504243.html

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

相关文章

C语言-指针(上)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 本篇文章将为大家介绍C语言中的核心内容-指针,指针在C语言的中知识内容比…

详解 JavaScript 中的数组

详解 JavaScript 中的数组 创建数组 注:在JS中的数组不要求元素的类型,元素类型可以一样,也可以不一样 1.使用 new 关键字创建 let array new Array()2.使用字面量方式创建(常用) let array1 [1,2,3,"4"]获取数组元素 使用下…

Python 教学平台,支持“多班教学”的课程授课方式|ModelWhale 版本更新

龙行龘龘、前程朤朤,ModelWhale 新一轮的版本更新,期待为大家带来更优质的使用体验。 本次更新中,ModelWhale 主要进行了以下功能迭代: 新增 课程(包括课件、作业、算力)按班级管理(团队版✓ …

Linux笔记-1

概述 简介 Linux是现在服务器上最常用的操作系统(OS - Operating system) - 所谓的操作系统本质上也是一个软件,是一个可以运行其他软件的容器如果一台服务器,没有安装操作系统,此时称之为裸机。裸机可以使用,在使用的时候需要使…

TCP与UDP基础

思维导图&#xff1a; TCP&#xff1a; 服务器 #include<myhead.h> #define SER_IP "192.168.252.163" #define SER_PORT 6666 int main(int argc, const char *argv[]) {//&#xff11;、创建用于监听的套接字int sfd-1;sfdsocket(AF_INET,SOCK_STREAM,0);/…

泰迪智能科技企业数据挖掘平台使用场景

企业数据挖掘平台助力企业数据挖掘&#xff0c;数据挖掘平台也在多个领域发挥着重要的作用。 企业数据挖掘平台具有数据抓取、数据清洗、数据分析、机器学习等多项功能&#xff0c;广泛应用于企业的各个领域&#xff0c;包括&#xff1a;金融行业、医疗行业、交通领域、教育、制…

Java对象大小计算

概述 在实际应用中&#xff0c;尤其是在进行JVM调优时&#xff0c;理解并正确估计对象大小是非常重要的&#xff0c;因为这直接影响到内存分配、垃圾回收效率以及应用程序的整体性能。 对象的组成 在Java中&#xff0c;计算一个对象的大小是为了了解它在内存中占用的确切空间…

【洛谷 P9240】[蓝桥杯 2023 省 B] 冶炼金属 题解(二分答案)

[蓝桥杯 2023 省 B] 冶炼金属 题目描述 小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V V V&#xff0c; V V V 是一个正整数&#xff0c;这意味着消耗 V V V 个普通金属 O 恰好可以冶炼出一个特殊金属 X&#xff0c;当普…

聊聊 HTTP 性能优化

作为用户的我们在 "上网冲浪" 的时候总是希望快一点&#xff0c;尤其是抢演唱会门票的时候&#xff0c;但是现实并非如此&#xff0c;有时候我们会遇到页面加载缓慢、响应延迟的情况。 而 HTTP 协议作为互联网世界的基础&#xff0c;从网站打开速度到移动应用的响应…

P8538 「Wdoi-2」灵山之上神风起 题解

「Wdoi-2」灵山之上神风起 传送门 题目背景 在天狗记者射命丸文的指&#xff08;放&#xff09;引&#xff08;水&#xff09;之下&#xff0c;灵梦一行人找到了山中的神社。 “在妖怪之山上还真的存在其他的神社啊。”灵梦感慨道。她们看到了由树木建造的神社正殿&#xf…

备战蓝桥杯---状态压缩DP进阶题1

我们来看一看一道比较难的问题&#xff08;十分十分的巧妙&#xff09;&#xff1a; 显然我们应该一行一行放&#xff0c;又竖的会对下一行产生影响&#xff0c;我们令横着放为0&#xff0c;竖着放的上方为1. 对于下一行&#xff0c;前一行放1的下面为0&#xff0c;但是会出现…

Flink基本原理 + WebUI说明 + 常见问题分析

Flink 概述 Flink 是一个用于进行大规模数据处理的开源框架&#xff0c;它提供了一个流式的数据处理 API&#xff0c;支持多种编程语言和运行时环境。Flink 的核心优点包括&#xff1a; 低延迟&#xff1a;Flink 可以在毫秒级的时间内处理数据&#xff0c;提供了低延迟的数据…