设计模式(二)工厂方法模式
发布日期:2021-09-17 01:32:52 浏览次数:3 分类:技术文章

本文共 2811 字,大约阅读时间需要 9 分钟。

一、模式定义

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

二、模式结构

这里写图片描述

我们可以看到工厂方法模式一共分为四个部分:

  • 抽象工厂(AbstractCreator)角色:担任这个角色的是工厂方法模式的核心,它是与应用程序无关的。任何在模式中创建对象的工厂类必须继承或者实现这个接口,在实际的系统中,这个角色常常有Java抽象类来实现。
  • 具体工厂(ConcreteCreator)角色:担任这个角色的是实现了抽象工厂接口的具体Java类。具体工厂角色含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
  • 抽象产品(AbstractProduct)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在实际应用中这个角色常常由Java的抽象类来实现。
  • 具体产品(ConcreteProduct)角色:这个角色实现了抽象产品角色所声明的接口,工厂方法所创建的每一个对象都是某个具体产品角色的实例。

三、模式动机

1、解决简单工厂模式中存在的“上帝类”的问题,将具体的生产任务放到子类中去。

2、解决简单工厂模式工厂角度不符合“开-闭”原则的问题。
3、解决简单工厂模式不能使用继承的问题。

这里写图片描述

四、实例分析

我们继续来分析上一篇博客中土豪开车的问题,我们使用了简单工厂模式后,程序好像已经很合理了,并且从实际生活来看也是比较符合逻辑的。但是可能会存在以下的问题。

1、如果土豪家里又买了很多车,那么Driver(工厂类)将会非常大,每次买一辆新的车都需要在这个工厂类中添加一个if-else语句,如果有的车坏了不能开了,还需要将对应的if-else语句删除,所以很麻烦,也不符合“开-闭”原则。

2、所有的产品创建都集中在Driver类中,一旦写错一个标点,所有的产品便都不能生产了。(可以想象成,只有一位司机师傅,这位司机师傅会开所有的车,一旦这一位司机师傅生病了,那么所有的汽车就都不能开了)。

所以我们可以使用工厂方法模式以下的改进。

首先,定义一个抽象的工厂类(Driver),这个抽象工厂类中有定义好的抽象方法getCar();用来告诉具体的工厂如何来获得汽车。

package com.myfactory.factory;public abstract class Driver {    public abstract Car getCar();}

然后,每一种车都配一个专门的司机,这个司机只负责或者一种车。

package com.myfactory.factory;public class BenzDriver extends Driver{
public Car getCar() { return new Benz(); }}

这里只写了Benz车的类,其他的车的类和这个类基本相同,不再贴出代码,最后会附上源码。

在客户端中,创建对应的Driver类,让特定的Driver来生产特定的汽车。

package com.myfactory.factory;public class Main {
public static void main(String[] args) throws Exception { //奔驰车司机 Driver driver = new BenzDriver(); //今天想做奥迪车 Car car = driver.getCar(); //开车 car.drive(); }}

通过改进,我们看到不再存在“上帝类”,有具体的工厂类来负责生产特定的产品,以后想要添加新的车的时候不必修改现有的工厂和产品的代码,只需要添加新的产品类和具体工厂类就可以了,不管是产品角度还是工厂角度都更加符合“开-闭”原则。

五、模式优点

  • 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
  • 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

六、模式缺点

  • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

七、适用场景

在以下情况下可以使用工厂方法模式:

1、一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。

2、一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
3、将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

八、模式在JDK中的应用

1、Object中的toString方法:Object仅仅定义了返回String,由Object的子类来决定如何生成这个字符串。

2、抽象类java.util.Calendar的getInstance方法将根据不同的情况返回不同的Calendar子类的对象。

源码下载:

转载地址:https://blog.csdn.net/xingjiarong/article/details/50001387 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:设计模式(五)创建者模式(Builder)
下一篇:设计模式(一)简单工厂模式

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年03月18日 12时00分38秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

html5 video视频资源保护,HTML5 视频播放 <video> 2019-04-21
html表头跟随滚动,JS实现table表格固定表头且表头随横向滚动而滚动_心善_前端开发者... 2019-04-21
rn webview加载本地静态html,React Native - Webview 加载本地文件 2019-04-21
dax powerbi 生成表函数_Power BI |DAX函数のCALCULATETABLE、CALENDAR函数以及相关表生成函数... 2019-04-21
编程之类的文案_如何锻炼写文案的能力? 2019-04-21
vscode 不能使用中文输入法_vscode中vim插件设置 2019-04-21
当集合a为空集时a的取值范围_1.1.2 集合间的基本关系 2019-04-21
vue 可合并表格组件_Vue实战046:详解Mixins混入使用和注意事项 2019-04-21
python包怎么做双重差分did分析_多变量相关性分析(一个因变量与多个自变量) 2019-04-21
fi sap 凭证冲销 稅_SAP中的成本要素 2019-04-21
mysql幻读是什么意思_MySQL中的幻读,你真的理解吗? 2019-04-21
mysql执行计划中性能最差的是_MySQL性能优化(七):MySQL执行计划,真的很重要,来一起学习吧... 2019-04-21
易语言执行mysql命令_易语言通过“打开”命令操作数据库 2019-04-21
mysql slave 1062_mysql主从同步slave错误1062 2019-04-21
mysql构造器_MySQL行构造器表达式优化(Row Constructor Expression) 2019-04-21
2008日志清理 server sql_SQL Server 2008 清除日志 2019-04-21
mac mysql root 权限_Mac平台重新设置MySQL的root密码 2019-04-21
mysql新增一列_MySQL-ProxySQL中间件 2019-04-21
mysql 30入门_30分钟带你快速入门MySQL教程 2019-04-21
kangle主机怎么配置MySQL_kangle web服务+easypanel主机控制面板快速搭建网站和数据库以及管理空间详细教程... 2019-04-21