简介: 创建型模式的核心干将,工厂、简单工厂、抽象工厂,还记得清么,一文回顾和对比下。

作者 | 弥高
来源 | 阿里技术公众号

前言

创建型模式的核心干将,工厂、简单工厂、抽象工厂,还记得清么,一文回顾和对比下。

一 为什么需要工厂

系统中总是需要创建对象的,一般使用new()来创建对象。创建对象可以是简单的new(),也可以有复杂的加工逻辑,如果在主程序中创建对象,那么就是将主干逻辑和创建对象的非主干逻辑耦合在了一起,工厂模式要做的就是将非核心的对象创建逻辑与主干逻辑解耦,通过调用工厂的创建方法直接获取到一个对象。

二 工厂模式中的角色划分

  • 抽象产品角色(都有)
  • 具体产品角色(都有)
  • 抽象工厂角色(工厂方法模式和抽象工厂模式有)
  • 具体工厂角色(都有)
  • 上下文角色(都有)——调用工厂获取对象

三 对工厂的基本认知

工厂方法总是基于一定的入参,返回对应的产品对象,即工厂是用来生产产品的。

工厂方法可能根据不同条件创建不同的具体产品实体,因此工厂方法的返回类型是抽象产品类型。

四 工厂模式的简单划分

1 简单工厂模式

产品有抽象层,但是工厂没有抽象层,在一个工厂中根据传参创建相应的产品类型。

如果需要新增产品族(例如在A_cpu,B_cpu之外新增C_cpu),那么需要在工厂方法中进行逻辑修改,没有做到开闭原则——对扩展开放,对修改封闭。

简单工厂模式就是静态工厂模式,不属于GOF23中的模式,就是一个简单的封装,在静态工厂模式中,工厂方法是静态的,所以叫做静态工厂方法。

2 工厂方法模式

产品有抽象层,工厂也有抽象层,一个工厂对应一个产品(即一个工厂只能创建一个产品类别)。

如果新增产品,只需要新增工厂,不需要对原有工厂逻辑进行修改,符合开闭原则。

3 抽象工厂模式

产品有抽象层,工厂有抽象层,一个工厂对应多个产品(即一个工厂可以创建多个产品类别)。

用于解决有多有产品类别(芯片、主板、显卡)情况下,产品族(A产品族、B产品族)的切换替代问题。

五 简单工厂模式详解

简单工厂模式下,只有一个工厂类,工厂角色没有抽象层次。

使用这一个工厂生产出不同的产品实现,例如使用CpuFactory这一个产品类中会生产出ACpu、BCpu等具体的产品实现。

如果要新增产品实现,例如CCpu,需要修改该工厂方法的代码。

简单工厂模式中,决定生成哪个产品的逻辑在工厂内实现。

1 DEMO:抽象产品接口

2 DEMO:具体产品实现

3 DEMO:具体产品实现

4 DEMO:简单工厂类

5 DEMO:测试类——调用工厂创建对象的客户端代码

六 工厂方法模式详解

工厂方法模式中,对工厂也进行了抽象,一个抽象工厂还是对应一个产品类别,例如CpuFacroy接口对应生产Cpu产品,但是具体生产的时候,将具体的产品实现交给每个具体的工厂实现去生产;即在CpuFactory接口下,有ACpuFactory和BCpuFactory,分别来生产ACpu和BCpu这2中具体的产品。

工厂方法模式中具体的工厂负责创建具体的产品,工厂内部的逻辑只负责创建对应对象,决定生成什么产品的逻辑在外部客户端,客户端通过选择使用具体工厂,间接决定了生成什么产品。

1 DEMO:产品抽象接口

2 DEMO:具体产品实现

3 DEMO:具体产品实现

4 DEMO:抽象工厂

5 DEMO:具体工厂实现

6 DEMO:具体工厂实现

7 DEMO:测试类——上下文

七 THINK:简单工厂&工厂方法模式的区别

简单工厂模式中工厂类没有抽象层,而工厂方法模式中工厂类有抽象工厂。

决定生成具体什么产品的逻辑在哪里实现?

  • 简单工厂模式中,客户端决定传递什么类型的参数,在工厂中根据不同的参数决定创建不同的对象,即工厂内部有决策创建产品的逻辑。
  • 工厂方法模式中,具体工厂内部很纯净,什么类型的工厂就负责创建对应的产品,决策的逻辑全部在客户端中实现。

当需要新增产品实现时,简单工厂模式需要修改工厂逻辑,工厂方法模式只需要新增具体工厂实现,不需要修改工厂内部逻辑。

八 THINK:工厂方法 & 抽象工厂模式的区别

1 工厂方法模式

工厂方法模式用于解决一个产品(Cpu),有多个产品族(ACpu,BCpu)的情况,以抽象产品作为工厂,例如CpuFactory,每个产品族对应一个具体工厂,例如ACpuFactory,BCpuFactory,即工厂方法模式以产品维度来建厂。

工厂方式模式中,多一个新的抽象产品的话需要新建立一个抽象工厂,例如新建MainboardFactory等。即如果需要新增产品线(XianKa),则需要新增抽象工厂(XianKaFactory);如果需要在某个产品(Cpu)下新增具体产品,则需要新增具体工厂(CCpuFactory)。

工厂方法模式中以抽象产品维度建厂,每个抽象产品一个工厂,当产品族(A,B,C……)增加的时候,需要为每个产品的抽象工厂新增具体工厂(CCpuFactory,CMainboardFactory,CXianKaFactory)。

2 抽象工厂模式

在工厂方法模式下,当产品线(品类:cpu/主板/显卡)和产品族(A/B/C)水平扩展后,如果要新增产品族,那么需要在所有工厂下面新增新产品族的所有产品,即在cpu工厂、主板工厂、显卡工厂……都新增C的具体工厂,这样显然改动太大,此时就要考虑使用抽象工厂模式。

抽象工厂模式下,以产品族维度来建厂,一个厂里有多个创建方法,每个创建方法负责创建一个产品线,例如有A工厂、B工厂,每个工厂里面有创建cpu的方法、创建主板的方法、创建显卡的方法,当需要新增一个产品族的时候,只需要新增一个工厂,例如C工厂,在该工厂中创建各个产品即可。

3 总结

工厂方法模式和抽象工厂模式的最大区别是工厂方法模式针对的是一个产品等级结构,而抽象工厂模式针对的是多个产品等级结构。

九 抽象工厂模式详解

1 抽象工厂模式角色

  • 抽象产品
  • 具体产品
  • 抽象工厂:以产品族维度建工厂类,类中含有多个抽象方法,每个方法对应创建一个产品。
  • 具体工厂:具体工厂实现抽象工厂,并实现里面的所有产品创建方法,创建属于当前具体产品对象。
  • 环境类:持有抽象工厂,并可以在运行时注入具体工厂。

2 DEMO:抽象产品

3 DEMO:具体产品

4 DEMO:抽象工厂

5 DEMO:具体工厂

6 DEMO:测试类——类似程序上下文

十 THINK:工厂模式中的方法一定是静态的吗?

在简单工厂中,工厂方法没有对应的抽象,可以定义为静态的。

在工厂方法模式和抽象工厂模式中,工厂都有对应的抽象接口,而接口中的抽象方法不能定义为静态,所以工厂方法也不能是静态的。

十一 THINK:对于接口中static的理解

接口interface以及接口中的方法都是public abstract的。

接口中的方法都是抽象方法,没有方法体,因此也不允许使用static来修饰(static方法表示可以被类调用,接口因为没有功能体,所以没有人调用,所以不允许声明为static)。

但是从JDK8开始,接口中方法可以有static,此时的方法必须有方法体,即接口中可以含有非抽象的方法,和抽象类一样了,接口中非抽象的方法不需要被实现,抽象的方法必须要求子类实现。

十二 工厂模式 & 抽象工厂的使用场景

一个系统不应当依赖于产品类实例如何被创建、组合、表达的细节,这是所有工厂模式都要关注解决的问题。

当系统中的产品有多个产品族,虽然对于任何一个具体请求只属于其中一个产品族,但是对于系统而言,应当面向产品族设计,即使用抽象工厂模式。

当系统中有多个产品族,并且这个产品族中的产品通常是在一起使用,一起创建的,如果这种约束需要在系统设计中体现出来,那么应当使用抽象工厂模式(例如:不管是A产品族,还是B产品族中的芯片、主板、磁盘这些产品通常需要一起创建)。

十三 抽象工厂模式的优缺点

1 抽象工厂的优点

分离了接口和实现

客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口,也就是说客户端从具体的产品中实现了解耦。

使切换产品族变得容易

因为一个具体的工厂代表的是一个产品族,比如上面例子中的A系列到B系列只需要切换一下具体的工厂。

2 抽象工厂的缺点

不太容易扩展新的产品

如果需要给这个产品族添加一个新的产品,那么就需要修改抽象工厂,需要在抽象工厂中添加新产品创建方法,同时需要给所有的具体工厂增加接口。

十四 最佳实践

都使用抽象工厂模式,按照产品族维度来建立工厂,如果只有一个产品那么工厂中就一个方法,如果有多个产品就多个方法。

原文链接
本文为阿里云原创内容,未经允许不得转载。

重温设计模式之 Factory的更多相关文章

  1. 设计模式 工厂-Factory

    在开始笔记之前先推荐一个网站:http://design-patterns.readthedocs.org/zh_CN/latest/index.html 网站对每一个Pattern都有详尽的解说.并 ...

  2. [学习笔记]设计模式之Factory Method

    写在前面 为方便读者,本文已添加至索引: 设计模式 魔法手札索引 在上篇笔记Abstract Factory设计模式中,时の魔导士创建了一系列的FoodFactory,并教会了其中一名霍比特人theC ...

  3. 设计模式学习--Factory Method

    What Factory Method:定义一个创建对象的接口,让子类来决定实例化哪一个类.Factory Method使一个类的实例化延迟到其子类. Why Factory Method是一个比較基 ...

  4. 简单工厂设计模式(Simple Factory Design Pattern)

    [引言]最近在Youtub上面看到一个讲解.net设计模式的视频,其中作者的一个理解让我印象很深刻:所谓的设计模式其实就是运用面向对象编程的思想来解决平时代码中的紧耦合,低扩展的问题.另外一点比较有见 ...

  5. 设计模式之Factory

    设计模式总共有23种模式这仅仅是为了一个目的:解耦+解耦+解耦...(高内聚低耦合满足开闭原则) 介绍: Factory Pattern有3种当然是全部是creational pattern. 1.S ...

  6. 一天一个设计模式——Abstract Factory抽象工厂模式

    一.模式说明 前面学习了工厂方法(Factory Method)模式.在工厂方法模式中,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理.这里学习的抽象工厂 ...

  7. 重温设计模式(三)——职责链模式(chain of responsibility)

    一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...

  8. 设计模式 - Abstract Factory模式(abstract factory pattern) 详细说明

    Abstract Factory模式(abstract factory pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/ ...

  9. 设计模式之Factory工厂模式的好处

    最最直观的好处就是吹牛逼,看着要比普通创建对象要屌 好看 一般情况下,我们创建对象使用的是new. Sample sample=new Sample(); 然而,实际情况会比这样复杂的多,比如说 Sa ...

  10. 设计模式之Factory模式 代码初见

    ObjectFactory就是通过Factory建造一个Object,比如说DBConnectionFactory就是专门建造DBConnection的工厂 BuilderFactory就是通过Fac ...

随机推荐

  1. PAT 甲级【1010 Radix】

    本题范围long型(35)^10 枚举radix范围上限pow(n/a0,1/m)上,考虑上限加1.范围较大.使用二分查找枚举 代码如下 import java.io.BufferedReader; ...

  2. 记录--纯CSS实现一个简单又不失优雅的步骤条

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 步骤条是一种用于引导用户按照特定流程完成任务的导航条,在各种分步表单交互场景中广泛应用.先来看一下几个主流前端 UI 框架中步骤条组件的样 ...

  3. SpringBoot集成drools

    目录 1.背景 2.需求 3.实现 3.1 引入jar包 3.2 编写drools配置类 3.3 编写Person对象 3.4 编写drl文件 3.5 编写kmodule.xml文件 3.6 编写Co ...

  4. BWO白鲸优化算法

    白鲸算法 ​ 白鲸算法(BWO)是一种新的元启发式算法,是一种基于群体的算法,其灵感来自于白鲸的行为,包括游泳,猎物和鲸落.在BWO的数学模型中构建了勘探,开发和鲸落阶段,并在开发阶段利用Levy飞行 ...

  5. mysql mysqldump 命令导出

    1.导出指定表的数据 mysqldump -t database -u user -p  --table_name1 table_name2 table_name3 >C:\db_script. ...

  6. KingbaseES 数据插入更新操作

    数据库使用过程中,经常会遇到一种场景:业务系统对数据进行dml操作,当数据库中数据不存在时,将数据做为新记录插入到表中,当数据库中数据存在时,对现有数据进行更新操作. 下面介绍KingbaseES中对 ...

  7. 参数 ora_input_emptystr_isnull 对于数据存储的影响

    原生的PG 对于 '' 和 null 认为是不同值:空值 和不确定值:而oracle 认为二者都是不确定的值.KingbaseES 为了兼容Oracle,增加了参数ora_input_emptystr ...

  8. Ant Design Vue Tree 选中子节点同时半选中父级节点

    需要实现的效果: 1.子菜单如果不是全部选中,一级菜单半选. 2.子菜单全选,一级菜单选中. 3.一级菜单选择,二级菜单全选. 4.没有二级菜单,则只控制一级菜单. 主要用到的属性是checked和h ...

  9. 【已解决】java.text.ParseException: Unparseable date

    今天在工作的时候遇到一个问题,我的一个字段queryDate保存不了,总是null值: java.text.ParseException: Unparseable date 报错的原因是日期格式转换错 ...

  10. Jetty的server模块

    启用server模块,执行如下命令: java -jar $JETTY_HOME/start.jar --add-modules=server 命令的输出,如下: INFO : server init ...