简单工厂模式

简单工厂模式


使用工厂模式创建对象的好处

通常我们在创建对象时最容易想到的就是new操作符,不过new操作符有许多局限:不够灵活,与业务类耦合度过大,也将初始化对象等无关业务细节暴露(我们只是要获取对象,不关心其他,初始化对象等细节操作何不交给其他类来完成?)。

一般可以采用工厂模式来解决这类问题。由一个第三方类(Factory类)来创建对象,将对象创建过程封装起来,降低系统耦合度。

概念

简单工厂模式(Simple Factory Pattern)并不属于GoF23个经典设计模式,不过它是学习其他工厂模式的基础。概念也比较简单。

  • 定义:定义一个工厂类,里面存在个static方法,根据不同参数返回不同实例,返回的实例通常具有共同父类。结构图如下:

简单工厂模式

实例

下面来举个简单的例子吧。想必很多同学都被家里长辈唠叨过怎么还不找女朋友。那我们就拿这个事来举个简单工厂的例子吧。

首先编写Product与ConcreteProduct类:

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
public abstract class Girl {
//女孩的品质
public void character() {
System.out.println("我是一个漂亮的,身材棒的女孩!");
}
//女孩的名字
public abstract void name ();
}
public class XiaoCao extends Girl {
@Override
public void name() {
System.out.println("我的名字是小草!");
}
}
public class XiaoHua extends Girl {
@Override
public void name() {
System.out.println("我的名字是小花!");
}
}
public class XiaoYe extends Girl {
@Override
public void name() {
System.out.println("我的名字是小叶!");
}
}

可以看到,我们创建了一个抽象类,并用这个类实现了三个具体类。

假如你现在有三个女朋友(不是让你脚踏三只船,只是为了例子说明),Mother要看看她们。我们很容易就想到下面实现:

1
2
3
4
5
6
7
8
9
10
11
public class Mother {
public static void main(String[] args) {
Girl girlFriend = new XiaoCao();//小草
girlFriend.character();
girlFriend.name();
}
}
运行结果:
我是一个漂亮的,身材棒的女孩!
我的名字是小草!

看起来很棒,运行结果也没问题。不过Mother看完小草不是那么满意,又想看小花了。或者Father、Sister什么的七大姑八大姨都要来看。这可怎么办,只能修改Mother类了。难道每次换想法我都要改一次吗?有没有一种方法可以直接给他们想要的,需要什么就给什么。

我们可以建立一个Factory类,你想看哪个直接取就是了。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GirlFactory {
public static Girl getGrilFriend (String name) {
Girl girl = null;
if (name.equals("小草")) {
girl = new XiaoCao();
} else if (name.equals("小花")) {
girl = new XiaoHua();
} else if (name.equals("小叶")) {
girl = new XiaoYe();
}
return girl;
}
}

Mother类变为:

1
2
3
4
5
6
7
8
9
10
11
public class Mother {
public static void main(String[] args) {
Girl girlFriend = GirlFactory.getGrilFriend("小花");
girlFriend.character();
girlFriend.name();
}
}
运行结果:
我是一个漂亮的,身材棒的女孩!
我的名字是小花!

将创建对象的职责交给第三方类(Factory)来执行,来达到解耦合的目的。什么七大姑八大姨想看也直接从Factory里取就是了。

不过缺点想必大家也可以看出,如果需要增加新的ConcreteProduct类时必须修改Factory类,这违背了开闭原则。当需要创建的对象很多时也势必会增加Factory类的复杂度,所以它适用于需要用Factory类创建少量对象的场合。

总结

缺点
  • Factory类负责相关所有对象的创建,职责过重,复杂度高
  • 添加新产品时必须修改Factory类,违背开闭原则
适用场景
  • 需要创建的对象不多时,Factory类复杂度不会太高
  • 客户端只需要知道传入的参数,对如何创建对象并不关心