工厂方法模式
# 一、概述
工厂方法(Factory Method)也称虚拟构造函数(Virtual Constructor),其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型,即将实例化操作交给子类执行。
# 1.1 解决了什么问题
假设有一个类,最初是为了生产电视创建的,所以大部分代码都是为了生产电视这个功能写的,里面和电视这款产品做了强耦合。
一段时间后,有了新的需求,要利用现在的工厂类生产投影仪,其实生产投影仪和生产电视在很多大的流程上是相同的是,只是一些细节、小功能方面有差异。但是由于之前的代码中已经和电视做了强绑定,如果要重用之前的这部分代码,稍加修改还可以勉强使用。
但是如果后续还有新的生产需求,比如要生产手机,那么代码将会变得非常复杂,难以维护,需要针对不同的需求进行特殊化处理。
而工厂方法模式则为每一种产品生成一个对应的工厂。
# 1.2 解决方案
工厂方法模式定义了一个创建对象的抽象方法,由子类决定要实例化的类。调用工厂方法的代码(客户端)不需要关心不同子类返回对象之间的内部差异,只关心接口的作用。
# 1.3 特点
优点:不直接在客户端创建具体产品的实例,降低了耦合性。 缺点:每增加一种产品就要相应的增加一个工厂类,比较繁琐。
# 二、实现方式
# 2.1 角色
工厂方法包含四个角色:
- 抽象工厂:是具体工厂角色必须继承的类或实现的接口。
- 具体工厂:由应用程序调用用来创建具体的产品对象。
- 抽象产品:具体产品要继承的类或实现的接口。
- 具体产品:具体工厂所创建的对象,是一个具体的产品实例。
# 2.2 代码
定义抽象的产品类,后续要具体生产的产品应当继承自此类:
/**
* 要生产的产品抽象类,具体的产品需要集成自此类
*/
abstract class Product {
public abstract void music();
public abstract void play();
}
/**
* 电视类
*/
class Television extends Product {
@Override
public void music() {
System.out.println("电视在放音乐");
}
@Override
public void play() {
System.out.println("电视在放电影");
}
}
/**
* 投影类
*/
class Projector extends Product {
@Override
public void music() {
System.out.println("投影仪在放音乐");
}
@Override
public void play() {
System.out.println("投影仪在放电影");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
定义一个工厂类,提供一个创建方法,该方法的返回类型为 Product,但是具体生产产品的工厂应当继承自此类,具体生产的对象也有其子类定义。
但是需要注意,工厂的主要作用是生产产品,但是出列生产之外,也可以提供一些默认实现或核心业务的处理。
/**
* 工厂类,其内部提供一个创建产品的方法,返回类型为 Product
*/
abstract class Factory {
/**
* 父类也可以提供一些默认实现
*/
abstract Product createProduct();
/**
* 工厂类中除了创建产品之外,还可以做一些核心业务逻辑的处理
*/
public void doSometh() {
System.out.println("执行 Factory 核心业务");
}
}
/**
* 具体创建工厂
*/
class TelevisionFactory extends Factory {
/**
* 子类根据需求创建不同的产品
* @return
*/
@Override
Product createProduct() {
return new Television();
}
@Override
public void doSometh() {
super.doSometh();
System.out.println("执行 TelevisionFactory 核心业务");
}
}
class ProjectorFactory extends Factory {
@Override
Product createProduct() {
return new Projector();
}
@Override
public void doSometh() {
super.doSometh();
System.out.println("执行 ProjectorFactory 核心业务");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
使用示例:
public class FactoryMethodTest {
public static void main(String[] args) {
String productType = "PJ";
Product product;
Factory factory;
if (productType.equals("TV")) {
factory = new TelevisionFactory();
} else if (productType.equals("PJ")) {
factory = new ProjectorFactory();
} else {
throw new IllegalArgumentException("参数类型错误");
}
factory.doSometh();
product = factory.createProduct();
product.music();
product.play();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
执行 Factory 核心业务
执行 ProjectorFactory 核心业务
投影仪在放音乐
投影仪在放电影
1
2
3
4
2
3
4
上次更新: 2023/11/01, 03:11:44