设计模式-抽象工厂模式

模式定义

抽象工厂模式,即Abstract Factory Pattern,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。

主要作用

允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。

解决的问题

解决工厂方法模式的缺点:每个工厂只能创建一类产品。

模式原理

UML类图

抽象工厂模式

模式组成

组成(角色) 关系 作用
抽象产品族(AbstractProduct) 抽象产品的父类 描述抽象产品的公共接口
抽象产品(Product) 具体产品的父类 描述具体产品的公共接口
具体产品(Concrete Product) 抽象产品的子类; 工厂类创建的目标类 描述生产的具体产品
抽象工厂(Creator) 具体工厂的父类 描述具体工厂的公共接口
具体工厂(Concrete Creator) 抽象工厂的子类; 被外界调用 描述具体工厂; 实现FactoryMethod工厂方法创建产品的实例

如何理解抽象产品族、抽象产品和具体产品的区别呢?请看下图:
概念区别

使用步骤

  1. 创建抽象工厂类,定义具体工厂的公共接口;
  2. 创建抽象产品族类 ,定义抽象产品的公共接口;
  3. 创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口;
  4. 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
  5. 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
  6. 客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例

模式优点

  1. 降低耦合
    抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展。

  2. 更符合开-闭原则
    新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可。

  3. 符合单一职责原则
    每个具体工厂类只负责创建对应的产品。

  4. 不使用静态工厂方法,可以形成基于继承的等级结构。

模式缺点

抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开放——封闭”原则。

应用场景

  1. 一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。
  2. 这个系统有多个系列产品,而系统中只消费其中某一系列产品。
  3. 系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现。

模式示例

示例背景

背景:假设有两间塑料加工厂(A厂仅生产容器类产品;B厂仅生产模具类产品);随着客户需求的变化,A厂所在地的客户需要也模具类产品,B厂所在地的客户也需要容器类产品;
冲突:没有资源(资金+租位)在当地分别开设多一家注塑分厂
解决方案:在原有的两家塑料厂里增设生产需求的功能,即A厂能生产容器+模具产品;B厂间能生产模具+容器产品。

抽象工厂类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 抽象工厂类,定义具体工厂的公共接口
*/
public abstract class Factory {
/**
* 生产容器
*
* @return
*/
public abstract AbstractProduct manufactureContainer();

/**
* 生产模具
*
* @return
*/
public abstract AbstractProduct manufactureMould();
}

抽象产品族类

1
2
3
4
5
6
7
8
9
10
11
12
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 抽象产品族类 ,定义具体产品的公共接口;
*/
public abstract class AbstractProduct {
/**
* 展示产品
*/
public abstract void show();
}

抽象产品类

容器产品抽象类

1
2
3
4
5
6
7
8
9
10
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 抽象产品类--容器 ,定义具体产品的公共接口
*/
public abstract class ContainerProduct extends AbstractProduct {
@Override
public abstract void show();
}

模具产品抽象类

1
2
3
4
5
6
7
8
9
10
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 抽象产品类--模具 ,定义具体产品的公共接口
*/
public abstract class MouldProduct extends AbstractProduct {
@Override
public abstract void show();
}

具体产品类

容器产品A类

1
2
3
4
5
6
7
8
9
10
11
12
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 具体产品类--容器A(继承抽象产品类), 定义生产的具体产品
*/
public class ContainerProductA extends ContainerProduct {
@Override
public void show() {
System.out.println("生产出了容器产品A...");
}
}

容器产品B类

1
2
3
4
5
6
7
8
9
10
11
12
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 具体产品类-容器B(继承抽象产品类), 定义生产的具体产品
*/
public class ContainerProductB extends ContainerProduct {
@Override
public void show() {
System.out.println("生产出了容器产品B...");
}
}

模具产品A类

1
2
3
4
5
6
7
8
9
10
11
12
13
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 具体产品类--模具A(继承抽象产品类), 定义生产的具体产品
*/
public class MouldProductA extends MouldProduct {

@Override
public void show() {
System.out.println("生产出了模具产品A...");
}
}

模具产品B类

1
2
3
4
5
6
7
8
9
10
11
12
13
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 具体产品类--模具B(继承抽象产品类), 定义生产的具体产品
*/
public class MouldProductB extends MouldProduct {

@Override
public void show() {
System.out.println("生产出了模具产品B...");
}
}

具体工厂类

A厂 - 生产模具+容器产品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法
* A厂 - 生产模具+容器产品
*/
public class FactoryA extends Factory {

@Override
public AbstractProduct manufactureContainer() {
return new ContainerProductA();
}

@Override
public AbstractProduct manufactureMould() {
return new MouldProductA();
}
}

B厂 - 生产模具+容器产品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法
* B厂 - 生产模具+容器产品
*/
public class FactoryB extends Factory {

@Override
public AbstractProduct manufactureContainer() {
return new ContainerProductB();
}

@Override
public AbstractProduct manufactureMould() {
return new MouldProductB();
}
}

客户端调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main.java.com.study.designPatterns.factory.abstracts.demoOne;

/**
* @author: whb
* @description: 客户端调用
*/
public class Client {
public static void main(String[] args) {
FactoryA mFactoryA = new FactoryA();
FactoryB mFactoryB = new FactoryB();
//A厂当地客户需要容器产品A
mFactoryA.manufactureContainer().show();
//A厂当地客户需要模具产品A
mFactoryA.manufactureMould().show();

//B厂当地客户需要容器产品B
mFactoryB.manufactureContainer().show();
//B厂当地客户需要模具产品B
mFactoryB.manufactureMould().show();

}
}

本文标题:设计模式-抽象工厂模式

文章作者:王洪博

发布时间:2018年07月12日 - 15:07

最后更新:2019年09月12日 - 10:09

原始链接:http://whb1990.github.io/posts/5a86ebac.html

▄︻┻═┳一如果你喜欢这篇文章,请点击下方"打赏"按钮请我喝杯 ☕
0%