前言

工厂方法模式是对简单工厂模式的改进,它通过对工厂类进行抽象形成一个抽象工厂接口,再让具体的工厂负责对应产品的创建,使得在增加产品的场景中也满足“开闭原则”。希望通过本文的学习,你可以掌握这种设计模式。

为了方便学习和交流,我会把「手撕设计模式」系列的代码上传到Github,需要的小伙伴可以到上面下载(记得顺手star一下哦~)。

GitHub地址:https://github.com/VeggieOrz/DesignPattern

文章目录

  • 前言
  • 1. 模式动机
  • 2. 模式定义
  • 3. 模式结构
  • 4. 模式实现
  • 5. 模式总结
    • 5.1 优点
    • 5.2 缺点
    • 5.3 应用场景
  • 参考资料

1. 模式动机

从上一篇博文「简单工厂模式」中,我们了解到它在增添新产品时必须修改工程类,不满足“开闭原则”。为了在简单工厂模式的基础上提高工厂类的拓展性,我们就引入了简单工厂模式,它的工厂类多了一层抽象工厂,具体产品对象的创建由和与之对应的具体工厂来负责

工厂方法模式降低了单个工厂的职责,每次新增产品时,只要加入新的具体产品类和具体工程类即可,符合开闭原则。(可以结合下图理解)

2. 模式定义

工厂方法模式(Factory Method Pattern)简称工厂模式,属于类创建模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类负责生成具体的产品类对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

3. 模式结构

工厂方法模式的结构图如下:

其中包含四个角色:

  • Product(抽象产品):抽象产品时定义产品的接口,是工厂方法模式所创建的超类,也是所有具体产品类的共同父类或接口。
  • ConcreteProduct(具体产品角色):具体产品实现了抽象产品接口,某种类型的具体产品3由专门的工厂创建,它们之间一一对应。
  • Factory(抽象工厂):这是工厂方法模式的核心,类中声明了用于创建产品的factoryMethod(),任何在模式中创建对象的工厂都必须实现该接口。
  • ConcreteFactory(具体工厂):具体工厂是抽象工厂的子类,实现了抽象工厂中定义的factoryMethod()方法,负责具体产品的创建。

4. 模式实现

(1)抽象产品

public interface Product {public void use();
}

(2)具体产品

public class ConcreteProductA implements Product{public void use() {System.out.println("This is Product A.");}
}

(3)抽象工厂

需要注意:工厂方法的返回类型必须是抽象产品类

public interface Factory {// 工厂方法factoryMethodpublic Product createProduct();
}

(4)具体工厂

public class ConcreteFactoryA implements Factory{public Product createProduct() {System.out.println("Product A is being produced.");return new ConcreteProductA();}
}

(5)工具类 and 配置文件

工具类主要用来进行配置文件的读取,读出想要创建的类型,然后通过Java提供的反射机制创建对应的对象。

public class XMLUtil {// 读取XML配置文件中具体类的类名,并返回一个实例对象public static Object getBean() throws Exception {try {// 创建文档对象DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc;doc = builder.parse(new File("./src/factoryMethod/config.xml"));// 获取包含类名的文本节点NodeList nodeList = doc.getElementsByTagName("className");Node classNode = nodeList.item(0).getFirstChild();String className = classNode.getNodeValue();// 通过类名生成实例对象并将其返回Class<?> c = Class.forName(className);Object obj = c.newInstance();return obj;} catch (Exception e) {// 如果该类名找不到就抛出异常throw new Exception("Sorry,This kind of product is not found");}}
}

写配置文件时候,要注意类的路径需要加上包名,否则会抛出java.lang.ClassNotFoundException异常。

<?xml version="1.0" encoding="UTF-8"?>
<config><className>factoryMethod.factory.ConcreteFactoryA</className>
</config>

(6)客户端

public class Client {public static void main(String[] args) {try {Factory factory;Product product;// 先通过读取配置文件和Java反射机制创建工厂factory = (Factory)XMLUtil.getBean();// 工厂负责创建相应的产品product = factory.createProduct();product.use();} catch (Exception e) {System.out.println(e.getMessage());}}
}

完成了这些只后,就知道了工厂方法模式的具体实现,但是上面代码还没体现到这种设计模式的优点。我们不妨思考一下,如果现在要挑添加一个ConcreteProductB,并将要创建的产品改为添加的这个产品,应该如何操作呢?

  • 先新建一个实现Product接口的ConcreteProductB类;
  • 然后再新建一个实现了Factory接口的ConcreteFactoryB类,专门负责产品类ConcreteProductB的创建;
  • 最后再将配置文件修改为ConcreteFactoryB类的路径即可。

由此可见,工厂方法模式添加新产品时也不需要对模式中原有的代码进行修改!

5. 模式总结

5.1 优点

  • 工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节
  • 能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。
  • 拓展性好,在系统中加入新产品时,不需要对已有代码进行修改,只要加上新的产品类和对应工厂类即可,完全符合开闭原则。

5.2 缺点

  • 系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一定的额外开销。
  • 增加了系统的抽象性和理解难度。

5.3 应用场景

  • 客户端不知道它所需要的对象的类,客户端不需要知道具体产品类的类名, 只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建。
  • 抽象工厂类通过其子类来指定创建哪个对象

参考资料

  1. 《Java设计模式》
  2. Factory Method | GitHub

如果看完本文感觉有所收获,别忘了点赞哦~

手撕设计模式之「工厂方法模式」(Java描述)相关推荐

  1. 设计模式系列之「工厂方法模式」

    "玛尼玛尼哄~~~",一个手持螺旋丸的鸣人出现了. "哦哈哟锅炸一马屎~~~",一个仙人模式的鸣人出现了. "死密码撒~~~",使用变身术的 ...

  2. Java 设计模式之静态工厂方法模式

    设计模式系列 创建型设计模式 Java 设计模式之单例模式 Java 设计模式之静态工厂方法模式 Java 设计模式之工厂方法模式 Java 设计模式之抽象工厂模式 Java 设计模式之Builder ...

  3. 工厂方法模式(Java)

    工厂方法模式(Java) 下面是关于我所写的所有设计模式代码(还是建议自己手打或者想一个别的例子练习一次) (https://github.com/lihang212010/DesignPattern ...

  4. 手撕设计模式之「简单工厂模式」(Java描述)

    前言 利用简单工厂模式可以实现对象创建和业务逻辑处理的分离,但存在工厂类职责过重,增添新产品违背开闭原则等问题.它不属于GoF 23种设计模式之一,但是它可以作为学习工厂方法模式前的一个很好的引导. ...

  5. 设计模式学习-工厂方法模式

    在上文(设计模式学习-简单工厂模式)的模拟场景中,我们用简单工厂模式实现了VISA和MASTERARD卡的刷卡处理,系统成功上线并运行良好,突然有一天老大跑来说,我们的系统需要升级,提供对一般银联卡的 ...

  6. 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)

    创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...

  7. 【设计模式学习】工厂方法模式

    cpp学习设计模式:工厂方法模式 在学习工厂方法模式之前,先回忆前面学的简单工厂模式: 简单工厂模式就是将对象的创建和逻辑的判断都交给了一个工厂类去做,这样做的优点是客户端不需要知道具体产品类的类名和 ...

  8. 设计模式系列之 工厂方法模式

    定义 定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类.工厂方法让类的实例化推迟到子类中进行. 该定义是对生产者一方的描述,涉及四种角色,包括接口.接口实现类.被实例化的类.抽象产品(隐 ...

  9. 设计模式 - 工厂方法模式 - 基于 Java 实现

    常见和工厂有关的设计模式 和工厂相关的设计模式主要有三种,工厂方法模式,抽象工厂模式: 在前面的博客中介绍了简单工厂模式,本篇博客主要介绍的是工厂方法模式 什么是工厂方法模式 工厂方法模式是简单工厂的 ...

最新文章

  1. 轻松一下——高考笑句
  2. SAP Spartacus popover Component 的单元测试
  3. Korney Korneevich and XOR(CF750F1/F2)
  4. vue隐藏浏览器_一分钟学会Vue的条件渲染和列表渲染
  5. 不得不说,其实你的性能优化手段已经过时了
  6. C++primer 9.5.5节练习
  7. 如何在 Mac 上关闭睡眠模式?
  8. 使用c语言生成斐波拉契(Fibonacci)数列的前20项并输出
  9. redis配合LUA脚本
  10. 人脸关键点检测的思考
  11. microsoft拼图闪退_笔者解答win10系统Microsoft Jigsaw(微软拼图)出现闪退的修复技巧...
  12. 北理python复试_北理考研复试-北京理工大学考研复试经验
  13. 精选黑科技资源站点,总会有你需要的干货!
  14. ​机器如何“猜你喜欢”?深度学习模型在1688的应用实践
  15. 关于某normal大学数据库登录的一个尝试
  16. SQLite查询记录总数
  17. 51单片机蜂鸣器播放天空之城
  18. java淘金者_Java游戏淘金者源码JAVA游戏源码下载
  19. 基于74LS148用Multisim仿真做8路抢答器
  20. 力荐几本学习MCSE的经典好书

热门文章

  1. optee中core_init_mmu_regs函数解读
  2. [mmu/cache]-Cache Type Register(CTR)寄存器介绍-InProgress
  3. Celery组件架构介绍
  4. 可以使任何人获得管理员权限的Windows 10系统漏洞
  5. 160个Crackme041之无源码修改Delphi程序
  6. 1.15 Java访问控制修饰符(public、 private、protected 和 friendly)
  7. 116. 飞行员兄弟【二进制枚举】
  8. 2.3.10 哲学家进餐问题
  9. 1.2.2 OSI参考模型(1)
  10. 幻灯片的其他操作(批量生成,重用,版式重设)