常用设计模式系列(二)—工厂方法模式

一、前言

hello各位小伙伴好,天气贼冷,多冻手,但是还是不能降低我编写设计模式讲解的热情。设计模式的魅力就像那冬天里的一把火,怎么也浇不灭;

上期讲解了简单工厂模式的应用场景及优缺点分析,今天开始我们的设计模式第二弹——工厂方法模式,其实工厂方法模式类似于简单工厂模式的一个升级;有印象的朋友可能还记得,上次我们讲到简单工厂模式可以生产出某一种类型的产品,我形象的使用了“鞋厂”来进行比喻,“鞋厂”目前只能生产出各种各样的鞋子,如果我需要的是衣服,是水杯,是其它类型的产品,那此时工厂类就不能满足新的具体产品类的生产了。具体如何解决,我们来了解下工厂方法模式。

二、什么是工厂方法模式

概念讲述

可以理解为简单工程模式的升级,简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂,简可以理解为,如果在简单工厂模式中,扩增具体产品信息,需要对原有工厂进行改造,当需求的产品类别增加到一定程度时,工厂较负责的产品线也相对复杂,当出现问题时,所有的产品的生产将会中断;

场景解释:

由于市场需求较大,“A老板”拿出自己全部身家,开办了上期我们所讲的“鞋厂”,随着客户越来越多,一些店家说,你们工厂生产鞋子,生产的皮鞋的原材料使用了皮质,可不可以生产皮包或者皮质钱包;“A老板”一想,这也是个赚钱的门路,随着客户的需求,“鞋厂”变成了生产多种商品的工厂。但是客户发现由于技术不成熟,发现生产的除了鞋子以外的产品,都没有鞋子的质量、款式好看,此时一个整合商“老板B”出现,联系了钱包厂购买钱包,皮包厂购买皮包,抢了“老板A”的生意,此时“老板A”找到“老板B”问道:“你是来砸场子的吧?”,“B老板”说:“兄弟,你这边鞋子的质量与款式我没得说,那是很好很好的,但是别的产品的确质量参差不齐,客户们都怨声道载,何不专心做鞋子呢,其它的产品交给专业的产品线来做,专业的人干专业的事情,岂不美哉,合作共赢。”

总结:

文中将一个生产多种类别(具体产品)的工厂,容易造成工厂压力较大,将具体的产品生产工作改为每个工厂去做,此时客户只需要要产品,中间的产品整合商对接多个工厂的方式使用的思维就是工厂方法模式。

用例图

工厂方法模式构成:

1.抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。

2.具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

3.抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。

4.具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

细心的朋友可能发现,相对简单工厂模式,将简单工厂模式中的工厂角色拆分为了抽象工厂和具体工厂,具体的产品的生产交给具体工厂来做。

UML图

三、代码实现

1.创建抽象工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.yang.factorymethod;

/**
* @ClassName AbstractFactory
* @Description 抽象工厂
* @Author IT小白架构师之路
* @Date 2020/12/7 21:53
* @Version 1.0
**/
public interface AbstractFactory {
/**
* 创建产品抽象方法
* @return
*/
public AbstractProduct createProduct();
}

2.创建抽象产品类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.yang.factorymethod;

/**
* @ClassName AbstractProduct
* @Description 抽象产品
* @Author IT小白架构师之路
* @Date 2020/12/7 21:57
* @Version 1.0
**/
public interface AbstractProduct {
/**
* 描述抽象方法
*/
public void hello();
}

3.创建具体产品工厂A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.yang.factorymethod;

/**
* @ClassName ConcreteFactoryA
* @Description 具体产品A工厂
* @Author IT小白架构师之路
* @Date 2020/12/7 21:59
* @Version 1.0
**/
public class ConcreteFactoryA implements AbstractFactory {
@Override
public AbstractProduct createProduct() {
return new ProductA();
}
}

4.创建具体产品工厂B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.yang.factorymethod;

/**
* @ClassName ConcreteFactoryB
* @Description 产品B工厂
* @Author IT小白架构师之路
* @Date 2020/12/7 22:02
* @Version 1.0
**/
public class ConcreteFactoryB implements AbstractFactory{
@Override
public AbstractProduct createProduct() {
return new ProductB();
}
}

5.创建具体产品A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.yang.factorymethod;

/**
* @ClassName ProductA
* @Description 产品A
* @Author IT小白架构师之路
* @Date 2020/12/7 22:01
* @Version 1.0
**/
public class ProductA implements AbstractProduct{
@Override
public void hello() {
System.out.println("我是产品A");
}
}

6.创建具体产品B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.yang.factorymethod;

/**
* @ClassName ProductB
* @Description 产品B
* @Author IT小白架构师之路
* @Date 2020/12/7 22:02
* @Version 1.0
**/
public class ProductB implements AbstractProduct{
@Override
public void hello() {
System.out.println("我是产品B");
}
}

7.创建测试客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.yang.factorymethod;

/**
* @ClassName Client
* @Description 注释
* @Author IT小白架构师之路
* @Date 2020/12/7 22:04
* @Version 1.0
**/
public class Client {
public static void main(String[] args) {
//产品A工厂
AbstractFactory factoryA = new ConcreteFactoryA();
AbstractProduct product = factoryA.createProduct();
product.hello();
//产品B工厂
AbstractFactory factoryB = new ConcreteFactoryB();
product = factoryB.createProduct();
product.hello();
}
}

8.运行结果如下

1
2
我是产品A
我是产品B

四、工厂方法模式优缺点及适用场景

优点:

1.在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品被实例化的细节,用户只需要关心所需产品对应工厂,无须关心创建细节,甚至无须关心具体产品的类名。

2.基于工厂角色和产品角色的多态性设计是工厂方法模式的关键;它能够让工厂自主确定创建何种产品对象,而如何创建对象的细节封装在具体工厂内部。

3.在系统中加入新产品时无需修改抽象工厂和抽象产品提供的接口,直接扩展具体工厂即可,扩展性较好。

缺点:

1.再添加新产品,则需要编写新的具体产品类,还要提供与之相对应的具体工厂类,当产品逐渐增多会造成系统的复杂度。

2.考虑到系统的可扩展性,需要引入抽象层,在客户端代码均使用抽象层进行定义,增加了系统的抽象性和理解难度。

适用场景

1.客户端不需要知道他所需要的对象的类时(只需要知道抽象产品对象类即可)。

2.在程序中需要子类覆盖父类对象时,可以使用。