小白也能看懂的工厂模式

在学习设计模式的时候,一开始对其中的工厂方法模式和抽象工厂模式有点混淆,网上查了一下,发现知乎也有人对这个问题进行提问,看来不止我不懂。一番学习好,发现其实很好理解。于是就有这篇文章的输出

要了解抽象工厂模式,就要先了解一下简单工厂模式和工厂方法模式,这几种工厂模式,是一步步迭代升级。至于实际工作用哪个更好呢,就要结合具体需求了。接下来的实例,不打算画UML图了,毕竟是面向小白,UML可能看不懂,也不对概念进行介绍了,需要的自行网上一搜就一大堆了。就以实际需求变动为例子,一步步介绍怎样通过不同的设计模式去应用。

作为Android程序员,最熟悉就是手机了,接下来就通过工厂生产手机作为例子。

普通写法

只有一个产品,正常写法就是如下,直接创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Client.java
/**使用手机的用户*/
public class Client {
public static void main(String[] args) {
MiPhone miPhone = new MiPhone();
miPhone.play();
}
}


# MiPhone.java
/**小米手机对象类*/
public class MiPhone {
public void play(){
System.out.println("使用小米手机");
}
}

如果某一天有钱想换成iphone,那应该怎样改了?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Client.java
public class Client {
public static void main(String[] args) {
//MiPhone miPhone = new MiPhone();
//miPhone.play();
Iphone iphone = new Iphone();
iphone.play();
}
}


# IPhone.java
/**新增的iphone手机对象类*/
public class Iphone {
public void play(){
System.out.println("使用苹果手机");
}
}

Client中,我们就才写了两行,都要全部换掉了,如果还有更多的方法,不都要全部一个个改吗?而且,这里的产品的创建是在Client中,正常逻辑我们又不会自己生产手机。这个时候,就可以采用简单工厂模式,专业的东西就让专业的工厂去做。

简单工厂模式

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
# SimpleFactory.java
/**新建一个工厂内,通过传递不同的参数,创建不同的产品并返回*/
public class SimpleFactory {

public static final String XIAOMI = "xiaomi";

@Nullable
public static ImplPhone createPhone(String phoneName){
if (XIAOMI.equals(phoneName)){
return new MiPhone();
}
return null;
}
}

# ImplPhone.java
/**定义一个手机的接口*/
public interface ImplPhone {
void play();
}

/**每个具体产品都去实现该接口并实现方法*/
public class MiPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用小米手机");
}
}

public class Client {
public static void main(String[] args) {
// 往工厂类中传递不同的值,就可以得到对应的产品。
ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.XIAOMI);
implPhone.play();
}
}

简单工厂模式,就是创建一个工厂类SimpleFactory,往工厂类根据传递不同的参数进行条件判断,生成返回不同的产品类。

这样改动,就可以避免两个问题:

  1. 把产品对象的创建,统一放在工厂类处理,而不是客户端自己创建

  2. 如果想换手机,直接传递不同的参数就好了。

使用简单工厂模式,应对更换手机的代码修改

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
public class SimpleFactory {

public static final String XIAOMI = "xiaomi";
public static final String APPLE = "apple";

public static ImplPhone createPhone(String phoneName){
if (XIAOMI.equals(phoneName)){
return new MiPhone();
}else if (APPLE.equals(phoneName)) {
return new IPhone();
}
return null;
}
}

# Iphone.java
public class IPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用苹果手机");
}
}

public class Client {
public static void main(String[] args) {
// 换成苹果手机,就直接传递不同参数生产Iphone手机了
//ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.XIAOMI);、
ImplPhone implPhone = SimpleFactory.createPhone(SimpleFactory.APPLE);、
implPhone.play();、
}
}

工厂方法模式

简单工厂模式,基本就可以满足我们的要求,但是接下来每次新增一个产品,都要去修改SimpleFactory类,这个就不满足我们的设计模式原则,尽量不要影响之前的类。于是,工厂方法模式闪亮登场。

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
# ImplFactory.java
/**定义一个工厂类*/
public interface ImplFactory {
ImplPhone cratePhone();
}

# MiFactory.java
/**实现工厂类,定义一个小米工厂,用于生产小米手机*/
public class MiFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new MiPhone();
}
}

# AppleFactory.java
/**实现工厂类,定义一个苹果工厂,用于生产iphone手机*/
public class AppleFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new IPhone();
}
}

public interface ImplPhone {
void play();
}

public class MiPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用小米手机");
}
}

public class IPhone implements ImplPhone {
@Override
public void play() {
System.out.println("使用苹果手机");
}
}

public class Client {

public static void main(String[] args) {
ImplFactory factory = new MiFactory();
// 如果想换手机,只需修改创建的工厂类
// ImplFactory factory = new AppleFactory();
ImplPhone phone = factory.cratePhone();
phone.play();
}
}

用了工厂方法模式,如果新增产品,比如想换华为呢,只需要新建一个华为工厂类去实现工厂接口,和新建一个华为手机内去实现手机接口,就不需要对原来的代码进行修改了。但是,人人一部手机是不够,还要平板了。。。于是,ipad,miPad就都出来了!

抽象工厂模式

上面的ImplFactory只是cratePhone(),根本就没办法生产平板,那么,就加多条生产线生产,能赚钱的机会怎么可以错过呢?

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
53
54
55
56
57
58
59
# ImplFactory.java
/**在原来的抽象工厂中,进行修改,增加一条平板的生产线,也就是添加一个方法*/
public interface ImplFactory {
ImplPhone cratePhone();
ImplPad createPad();
}

public class AppleFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new IPhone();
}

@Override
public ImplPad createPad() {
return new Ipad();
}
}

public class MiFactory implements ImplFactory {
@Override
public ImplPhone cratePhone() {
return new MiPhone();
}

@Override
public ImplPad createPad() {
return new MiPad();
}
}

public interface ImplPad {
void play();
}

public class Ipad implements ImplPad {
public void play(){
System.out.print("使用ipad");
}
}

public class MiPad implements ImplPad {
public void play(){
System.out.print("使用小米pad");
}
}


public class Client {

public static void main(String[] args) {
ImplFactory factory = new MiFactory();
ImplPhone phone = factory.cratePhone();
phone.play();

ImplPad pad = factory.createPad();
pad.play();
}
}

改动还是挺大的,但至少能实现需求。接下来有其他厂商也要生产手机和平板,只需要实现ImplFactory就可以了。其实,上面的处理方式,就是抽象工厂模式

啊?别惊讶,一不小心就应用上了。仔细对比一下区别就可以理解:

工厂方法模式,重点在方法,通过实现同一个方法,就可以创建不同的产品。
抽象工厂模式,是在工厂方法模式发展上去的,方法也可以创建不同的产品,但是,这个工厂接口,变更加抽象了,在里面可以实现多个方法,而不是单一产品了。

公众号:亦袁非猿

欢迎关注,交流学习