设计模式之死磕工厂方法模式(原创)

简介: 在 设计模式之工厂模式 中,我们提到过工厂模式仔细区分的话分为三种,分别是简单工厂模式、工厂方法模式以及抽象工厂模式。在上面已经介绍完毕了工厂模式(也就是简单工厂模式)。

在 设计模式之工厂模式 中,我们提到过工厂模式仔细区分的话分为三种,分别是简单工厂模式、工厂方法模式以及抽象工厂模式。在上面已经介绍完毕了工厂模式(也就是简单工厂模式)。本篇文章主要学习的是工厂模式的第二种,工厂方法模式。

注:本文是基于 设计模式之工厂模式 的文章之上进行编码以及项目说明

首先回顾下工厂模式的基本概念:我们在创建对象时不会对客户端直接暴露创建逻辑,而是 通过使用一个共同的接口根据不同的条件来指向具体想要创建的对象。

通过一个共同的接口根据不同的条件来指向想要创建的对象,这个切入点肯定没错,在上一篇文章也讲到,我们通过使用工厂模式的优点在于一个调用者想创建一个对象,只要知道其名称(也就是不同的标签)就可以在工厂获取具体的对象;其次,在这种设计模式下会屏蔽产品的具体实现,调用者只关心产品的接口、无需关心内部实现。

但是,这样也会带来一个问题,如果我想增加一个(也就是具体的对象),那就需要扩展工厂类(也就是首先要增加不同的标签,然后增加不同标签所对应的对象)。如果这样操作的话,就违背了“开闭”原则。那么,什么是开闭原则?

在 设计模式概念与简介 这篇文章中简单介绍了开闭原则,那么这里对开闭原则做更加详细的分析。

开闭原则(OCP)是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。开、闭的字面理解就是对于扩展是开放的,对于修改是关闭的,这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。更通俗一点,也就是:软件系统中包含的各种组件,例如模块(Modules)、类(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,引入新功能。

既然开闭原则是如此的重要,那么开发者应该如何实现开闭原则

A:抽象约束 

抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,可以跟随需求的变化而变化。因此,通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放,其包含三层含义:

通过接口或抽象类约束扩散,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法。

参数类型,引用对象尽量使用接口或抽象类,而不是实现类,这主要是实现里氏替换原则的一个要求

抽象层尽量保持稳定,一旦确定就不要修改

B:元数据(metadata)控件模块行为 

编程是一个很苦很累的活,那怎么才能减轻压力呢?答案是尽量使用元数据来控制程序的行为,减少重复开发。什么是元数据?用来描述环境和数据的数据,通俗的说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。

C:制定项目章程 

在一个团队中,建立项目章程是非常重要的,因为章程是所有人员都必须遵守的约定,对项目来说,约定优于配置。这比通过接口或抽象类进行约束效率更高,而扩展性一点也没有减少。

D:封装变化 

对变化封装包含两层含义: 

(1)将相同的变化封装到一个接口或抽象类中 

(2)将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。 

封装变化,也就是受保护的变化,找出预计有变化或不稳定的点,我们为这些变化点创建稳定的接口。

开闭原则的具体实现与相互关系:

开闭原则被称作面向对象设计的终极目标。因此,针对开闭原则的实现方法,一直都有面向对象设计的大师费尽心机去研究开闭原则的实现方式。但是在平时的开发中我们已经直接或者间接的已经接触到了开闭原则的设计理念。比如,设计模式概念中提到的里氏代换原则、依赖倒转原则、接口隔离原则 以及常用的接口、抽象类等等,都可以看作是开闭原则的具体实现方法。

那么在回到上面的问题,当需求发生变化的时候,简单工厂模式下进行修改操作的话是违背开闭原则的(当然你说这样也无所谓,这个功能怎么实现我不管、反正可以用就行),那么如何解决上面的问题?

比较高效和容易理解的方式是,在定义一个抽象的英雄工厂类型的基类,让子类自己去实现该基类(也就是工厂与实例对象互相对应)。

首先还是跟上一篇文章一样,基本代码不变:

img_3f4488e5f296bb9855841faa07e73377.png
英雄规范

接着是已持有的三个英雄:

img_3552208c141c067c5fe80a2ef9d65340.png
Ashe
img_ab5703d856b7807b352a62724b07d0f5.png
MasterYi
img_eaeefe9f5f955a57066ca2855172b155.png
Timor

上面的代码和简单工厂模式下的代码都是一样的,针对上面的问题,我们提到可以定义一个抽象的英雄工厂类型的基类

img_104f16a2a165647fac80729cc79bb8a9.png
定义基类

其中,这里基类的抽象方法,返回的是具体的英雄参数类型,那么通过子类就可以进行具体的操作(将对象返回出去即可)三个具体的英雄对应三种具体的工厂

img_be7501c623c04761f8c485a374a985c4.png
射手工厂
img_15f05cb99b9b5ab7b44b20cdc01bcc21.png
法师工厂
img_ff9b6f3abbca5feb79470f8b072aa247.png
战士工厂

定义完三个工厂以后,我们就可以测试使用了:

img_313c67e88bb1b5e57386181ce18eb5ff.png
测试工厂方法模式

可能会说,这两种模式有什么区别?这里先上一下两种工厂模式下的测试类比较:

img_c4de1b17cbd7eb23ce3907979d6f6cd8.png
两种模式测试比较

其中,红色箭头的是简单工厂模式(这种模式下将所有的标签和对象全部统一在这里进行管理使用)

蓝色箭头代表的是工厂方法模式,在这种模式下,各个工厂内对象依据工厂类型不同进行创建。

简单工厂模式和工厂方法模式的比较:

简单工厂模式是专门定义一个类(工厂类)来负责创建其他类的实例,被创建的实例通常都具有共同的父类。它又称为静态工厂方法模式。本质是由一个工厂类根据传入的参数动态决定创建那一个产品类(这些产品类继承自一个父类或接口)的实例对象。在这种模式下工厂类是整个模式的关键,它包含必要的逻辑判断能够根据外界给定的信息决定究竟应该创建那个具体类的对象。

工厂方法模式是粒度很小的设计模式,因为模式的表现是一个抽象的方法。提前定义用于创建对象的接口让子类决定实例化具体的某一个类,即在工厂和产品中间增加一个接口(或者抽象类),工厂不再负责产品的创建,由接口针对不同条件返回具体的实例,由具体类实例去实现。工厂方法模式是简单工厂模式的衍生解决了之前简单工厂模式下带来的问题。完全实现了开闭原则。工厂方法模式是对简单工厂模式进行了抽象。有一个抽象的Factory类(接口或者抽象)这个类不在负责具体的产品生产(也就是new 对象),而是只指定规范,具体的实现由子类完成。在这种模式下,工厂类和产品往往可以互相对应。即一个抽象工厂对应一个抽象产品,一个具体的工厂对应一个具体的产品,这个具体的工厂就负责生产对象的产品(也就是上面的蓝色箭头)

简单工厂模式和工厂方法模式的优缺点:

简单工厂模式:

优点:工厂类含有必要的逻辑判断,可以依据不同的标签创建不同的对象,实现了对责任的分割,耦合性较低。有利于整个软件体系结构的优化

缺点:拓展性相对较低(因此出现了工厂方法模式)

工厂方法模式:

优点:这种模式是为了克服简单工厂模式下的缺点(主要是开闭原则),这种模式下每个具体的工厂类只完成单一任务,代码简洁,拓展性强

缺点:不易于维护,修改产品对象也要修改对应的工厂类(修改多个产品就要修改多个工厂)

简单工厂模式和工厂方法模式的适用范围:

简单工厂模式:工厂类负责创建的对象比较少,客户只知道传入了工厂类的参数,对于创建的逻辑不关心。且使用一个共同的接口根据不同的条件来指向具体想要创建的对象可以使用简单工厂模式

工厂方法模式:当一个类不知道它所必须创建对象的类或者一个类希望由子类来指定它所创建的对象时;当类将创建的需的职责委托给帮助类中的某一个,并且希望得到指定帮助类的信息,可以使用工厂方法模式

参考资料:百度百科

如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。

Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

相关文章
|
7月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
205 16
|
7月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
214 0
|
7月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
196 0
|
7月前
|
设计模式 安全 Java
并发设计模式实战系列(12):不变模式(Immutable Object)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十二章,废话不多说直接开始~
168 0
|
7月前
|
设计模式 算法 Java
设计模式觉醒系列(04)策略模式|简单工厂模式的升级版
本文介绍了简单工厂模式与策略模式的概念及其融合实践。简单工厂模式用于对象创建,通过隐藏实现细节简化代码;策略模式关注行为封装与切换,支持动态替换算法,增强灵活性。两者结合形成“策略工厂”,既简化对象创建又保持低耦合。文章通过支付案例演示了模式的应用,并强调实际开发中应根据需求选择合适的设计模式,避免生搬硬套。最后推荐了JVM调优、并发编程等技术专题,助力开发者提升技能。
|
12月前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
655 11
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
7月前
|
设计模式 Prometheus 监控
并发设计模式实战系列(20):扇出/扇入模式(Fan-Out/Fan-In)(完结篇)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第二十章,废话不多说直接开始~
231 0
|
11月前
|
设计模式
「全网最细 + 实战源码案例」设计模式——模式扩展(配置工厂)
该设计通过配置文件和反射机制动态选择具体工厂,减少硬编码依赖,提升系统灵活性和扩展性。配置文件解耦、反射创建对象,新增产品族无需修改客户端代码。示例中,`CoffeeFactory`类加载配置文件并使用反射生成咖啡对象,客户端调用时只需指定名称即可获取对应产品实例。
223 40
|
9月前
|
设计模式 Java 关系型数据库
设计模式:工厂方法模式(Factory Method)
工厂方法模式是一种创建型设计模式,通过将对象的创建延迟到子类实现解耦。其核心是抽象工厂声明工厂方法返回抽象产品,具体工厂重写该方法返回具体产品实例。适用于动态扩展产品类型、复杂创建逻辑和框架设计等场景,如日志记录器、数据库连接池等。优点包括符合开闭原则、解耦客户端与具体产品;缺点是可能增加类数量和复杂度。典型应用如Java集合框架、Spring BeanFactory等。

热门文章

最新文章