Java设计模式—工厂方法模式

工厂方法模式(Factory Method Pattern)

工厂方法模式是一种创建型设计模式,定义一个创建对象的接口,让子类决定实例化哪一个类。

一、模式概述

1.1 定义

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

1.2 适用场景

  • 当一个类不知道它所必须创建的对象的类时
  • 当一个类希望由它的子类来指定它所创建的对象时
  • 当类将创建对象的职责委托给多个帮助子类中的某一个时

1.3 UML 类图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+----------+       +----------+
| Product | | Factory |
+----------+ +----------+
| +use() | | +create()|
+----△-----+ | #createProduct()|
| | #registerProduct()|
| +-----△-----+
+----------+ |
| IDCard | +----------+
+----------+ |IDCardFactory|
| +use() | +----------+
+----------+ | #createProduct()|
| #registerProduct()|
+----------+

1.4 工厂模式分类

类型说明适用场景
简单工厂一个工厂类,根据参数创建不同产品产品较少,不会频繁增加
工厂方法每个产品对应一个工厂类产品种类可能扩展
抽象工厂创建多个产品族多个产品族,产品之间有关联

二、代码实现

2.1 定义 Product 抽象类

Product类来表示产品,这个类中只声明了抽象方法use()等待子类重写。

1
2
3
4
5
6
7
8
/**
* @author ikun
* @date 2024年06月28日 14:35
*/
public abstract class Product {
public abstract void use();
}

1.2 定义Factory抽象类

Factory类使用了模板模式,本类定义了抽象方法 creatProductregisterProduct,定义并实现了 create 方法,通过调用这个方法实现产品的注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author ikun
* @date 2024年06月28日 14:50
*/
public abstract class Factory {

public Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}

protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}

1.3 定义IDCard类

继承了 Product 类并实现了 use() 方法,构造器初始化了属性 owneridNum,并输出语句进行提示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* @author ikun
* @date 2024年06月29日 09:17
*/
public class IDCard extends Product {
private String owner;
private int idNum;

IDCard(String owner, int idNum) {
System.out.println("制作" + owner + "(" + idNum + ")" + "的ID卡...");
this.owner = owner;
this.idNum = idNum;
}

@Override
public void use() {
System.out.println("使用" + owner + "(" + idNum + ")" + "的ID卡...");
}

public String getOwner() {
return owner;
}
}

1.4 定义IDCardFactory类

这个类继承了 Factory 并实现了其两个抽象方法,creatProduct 方法通过生成 IDCard 的实例来生成产品,registerProduct 通过将 IDCardowner 保存到 List 数组中实现注册产品。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @author ikun
* @date 2024年06月29日 10:07
*/
@SuppressWarnings("all")
public class IDCardFactory extends Factory {

private List<String> owners = new ArrayList<>();
private int idNum = 1001;

@Override
protected Product createProduct(String owner) {
return new IDCard(owner, idNum++);
}

@Override
protected void registerProduct(Product product) {
owners.add(((IDCard) product).getOwner());
}
}

1.5 测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @author ikun
* @date 2024年06月29日 10:24
*/
public class RunMain {
public static void main(String[] args) {
Factory factory = new IDCardFactory();
Product card1 = factory.create("小明");
Product card2 = factory.create("小红");
Product card3 = factory.create("小刚");
card1.use();
card2.use();
card3.use();
}
}

2.6 运行结果

gc-1

三、模式分析

3.1 优缺点

优点缺点
符合开闭原则,扩展性好类的数量增加
符合单一职责原则增加系统抽象性
客户端无需知道具体产品类名增加系统复杂度

3.2 实际应用

  • Spring 的 BeanFactory:创建 Bean 实例
  • JDBC 的 DriverManager:获取数据库连接
  • 日志框架 SLF4J:LoggerFactory.getLogger()
1
2
3
// Spring 工厂模式示例
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = context.getBean("userService", UserService.class);

四、总结

具体的实现内容根据工厂模式适用场景不同而变化,但是只要是工厂模式,在生成实例时就一定会用到模板模式。

设计原则:依赖倒置原则——依赖抽象,不要依赖具体类。高层模块不应该依赖低层模块,两者都应该依赖抽象。