什么是“工厂方法模式”
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
我们来看看工厂方法模式的UML图:
从类图中我们可以看到,工厂方法有两个平行的接口(抽象类),一个是Product,一个是Factory。
他们具体什么意思呢, 我们可以先来看看例子,然后再理解这个类图。
为什么要使用“工厂方法模式”
背景:假如我们需要使用 Java 生产很多款手机, 那么我们最传统最简单的做法似乎是这样子:
1 | public Phone createPhone(String name){ |
这样做貌似没什么不对,但是我们可以仔细想想,假如我们需要生产更多品牌的手机呢?再加入我们需要不同国家生产适合该国家的手机呢(比如港版、美版等等)? 出现这类需求的时候, 我们这么做就显得有些力不从心了。
这个时候, 工厂方法模式就该登场了。
如何使用“工厂方法模式”
根据类图,我们首先需要两个顶层的接口
1
2
3
4
5
6
7
8
9
10/**
* 手机的抽象类
* */
public abstract class Phone {
public String name;
public double price;
public abstract void showPhone();
}/**
- 工厂的抽象类
*/
public abstract class PhoneFactory {public abstract Phone createPhone(String name);
}
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
2. 有了顶层接口,我们需要**具体的手机类**
```java
//华为
public class HuaWeiPhone extends Phone {
public HuaWeiPhone(String name, double price) {
super.name = name;
super.price = price;
}
@Override
public void showPhone() {
System.out.println("华为被生产出来啦=============");
System.out.println(name + ": " + price);
}
}
//小米
public class XiaoMiPhone extends Phone {
public XiaoMiPhone(String name, double price) {
super.name = name;
super.price = price;
}
@Override
public void showPhone() {
System.out.println("小米被生产出来啦=============");
System.out.println(name + ": " + price);
}
}
//Iphone
public class IPhone extends Phone {
public IPhone(String name, double price) {
super.name = name;
super.price = price;
}
@Override
public void showPhone() {
System.out.println("苹果被生产出来啦=============");
System.out.println(name + ": " + price);
}
}有了具体的手机类之后,我们就可以把具体的工厂创建出来了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* 某个国家的工厂
*/
public class PhoneFactoryImpl extends PhoneFactory {
Phone phone;
public Phone createPhone(String name) {
if (name.equals("华为")){
phone = new HuaWeiPhone(name,3999.99);
}else if (name.equals("小米")){
phone = new XiaoMiPhone(name,2999.99);
}else if (name.equals("苹果")){
phone = new IPhone(name,6999.99);
}
return phone;
}
}在这个方法中,其实可以使用反射技术实现在运行时动态地创建相应的对象,这样就可以在新增某款手机的时候避免修改代码。但是为了简单起见,我们在这里不使用反射技术,直接使用原始的方法。
所有东西都准备齐全了, 我们可以生产手机了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class CreatePhoneTest {
public static void main(String[] args){
Phone phone;
PhoneFactory factory = new PhoneFactoryImpl();
phone = factory.createPhone("小米");
phone.showPhone();
phone = factory.createPhone("苹果");
phone.showPhone();
phone = factory.createPhone("华为 ");
phone.showPhone();
}
}运行结果如下:
1
2
3
4
5
6小米被生产出来啦=============
小米: 2999.99
苹果被生产出来啦=============
苹果: 6999.99
华为被生产出来啦=============
华为: 3999.99在这个例子中, 我们只实现了一种具体的工厂, 假如需要不同的工厂生产不同类型的手机, 工厂方法模式无疑提供了很大的便利和可拓展性。
那么, 总结来了
在上面的例子中, 我想各位同学也都理解了UML类图的具体含义。
工厂方法模式是一种很实用、 拓展性强的模式。
优点:
封装性强: 我们只需要知道某个手机类或者手机名字的约束字符串,就可以进行生产。(本例中还需要去工厂实现类中添加一个判断分支,在具体的应用场景中我想没人会使用判断分支在工厂类中,一般都是使用反射)
拓展性好:比如我们还需要增加一款魅族手机,那么我们只需要实现 MeiZuPhone 类就可以了。
屏蔽了产品类:这一点非常有用,屏蔽了手机内部的具体实现, 只需要知道他们实现了 Phone 接口就行了。
使用场景:
工厂方法模式是 new 一个对象的替代品, 所以在需要新建一个对象的时候都可以使用, 但是要考虑使用后代码的复杂度。
与工厂方法模式类似的抽象工厂模式将在下一篇文章发表。欢迎关注
感谢阅读本博客。
欢迎关注我的博客:https://li-weijian.github.io/
欢迎关注我的CSDN:https://blog.csdn.net/qq352642663
需要联系请加QQ:352642663
欢迎联系我共同交流