HeadFirst设计模式-工厂模式(基于汽车工厂和手机工厂)

工厂模式

本次主要讲述三个内容:

依赖倒置原则

设计原则:要依赖抽象,不要依赖具体类。

不能让高层组件依赖底层组件,而且,不管高层或底层组件,“两者”都应该依赖于抽象。
这个原则告诉我们,应该重写代码以便于我们依赖抽象类,而不依赖具体类。

指导方针:

  • 变量不可以持有具体类的引用。(如果使用new,就会持有具体类的引用。你可以改用工厂类避开这样的做法。)
  • 不要让类派生自具体类。(如果派生自具体类,你就会依赖具体类。请派生自一个抽象(接口或抽象类))
  • 不要覆盖基类中已实现的方法。(如果覆盖基类已经实现的方法,那么你的基类将就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享)

简单工厂模式

简单工厂模式不是一个“真正的”设计模式,只能说是一种编程习惯。
比如建立一个抽象类Car,然后用子类来继承。用SimpleCarFactory来生成对象(里面包含选择相应对象的逻辑处理),CarStrore直接调用SimpleCarFactory即可。
tu1
如上图所示。
代码实现如下:
Car :

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
package com.bestqiang.easyfactory;

/**
* @author BestQiang
*/
public abstract class Car {
private String color;
private String price;
private String speed;

public abstract void go();
public abstract void clear();

@Override
public String toString() {
return "Car{" +
"color='" + color + '\'' +
", price='" + price + '\'' +
", speed='" + speed + '\'' +
'}';
}

public void sayHello() {
System.out.println("我是" + color + "汽车," + " 我的价格是: " + price + "," + "速度是:"
+ speed);
}

public String getSpeed() {
return speed;
}

public void setSpeed(String speed) {
this.speed = speed;
}

public String getColor() {
return color;
}

public String getPrice() {
return price;
}

public void setColor(String color) {
this.color = color;
}

public void setPrice(String price) {
this.price = price;
}
}

BlueCar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.bestqiang.easyfactory;

/**
* @author BestQiang
*/
public class BlueCar extends Car {

public BlueCar() {
super("blue","2000$", "888km/s");
}

@Override
public void go() {
System.out.println("蓝汽车清洗完成了!");
}

@Override
public void clear() {
System.out.println("蓝汽车可以开走了!");
}
}

RedCar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.bestqiang.easyfactory;

/**
* @author BestQiang
*/
public class RedCar extends Car {

public RedCar() {
super("red","1000$", "999km/s");
}

@Override
public void go() {
System.out.println("红汽车可以开走了!");
}

@Override
public void clear() {
System.out.println("红汽车清洗完成了!");
}
}

SimpleFactory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.bestqiang.easyfactory;

/**
* @author BestQiang
*/
public class SimpleCarFactory {
public Car createCar(String type) {
Car car = null;
if(type.equals("red")) {
return new RedCar();
} else if (type.equals("blue")) {
return new BlueCar();
}
return car;
}
}

CarStore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.bestqiang.easyfactory;

/**
* @author BestQiang
*/
public class CarStore {
SimpleCarFactory simpleCarFactory = new SimpleCarFactory();

public Car orderCar(String type) {
Car car = simpleCarFactory.createCar(type);
car.sayHello();
car.clear();
car.go();
return car;
}
}

Main:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.bestqiang.easyfactory;

/**
* @author BestQiang
*/
public class Main {
public static void main(String[] args) {
// 没有依赖抽象类,下面的工厂模式会对其改进
CarStore carStore = new CarStore();
Car blue = carStore.orderCar("blue");
Car red = carStore.orderCar("red");
System.out.println(blue);
System.out.println(red);
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
我是blue汽车, 我的价格是: 2000$,速度是:888km/s
蓝汽车可以开走了!
蓝汽车清洗完成了!
我是red汽车, 我的价格是: 1000$,速度是:999km/s
红汽车清洗完成了!
红汽车可以开走了!
Car{color='blue', price='2000$', speed='888km/s'}
Car{color='red', price='1000$', speed='999km/s'}

Process finished with exit code 0

工厂方法模式

刚才的简单工厂模式,只有一个工厂,不能动态的切换工厂。
所有的工厂模式都用来封装对象的创建。工厂方法模式(Factory Method Pattern)通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。等于说是
如下图所示:
tu2
简单工厂的做法,可以将对象的创建封装起来,但是简单工程不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。Main新建工厂的时候直接new抽象类就ok了。

工厂类的实现代码:
CarStoreF:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.bestqiang.factory;

import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.SimpleCarFactory;

/**
* @author BestQiang
*/
public abstract class CarStoreF {

public Car orderCar(String type) {
Car car = createCar(type);
car.sayHello();
car.clear();
car.go();
return car;
}

protected abstract Car createCar(String type);

}

HuaweiCarStore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.bestqiang.factory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/**
* @author BestQiang
*/
public class HuaweiCarStore extends CarStoreF {
@Override
protected Car createCar(String type) {
Car car = null;
if(type.equals("red")) {
System.out.println("Huawei出品");
return new RedCar();
} else if (type.equals("blue")) {
System.out.println("Huawei出品");
return new BlueCar();
}
return car;
}
}

XiaomiCarStore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.bestqiang.factory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/**
* @author BestQiang
*/
public class XiaomiCarStore extends CarStoreF {
@Override
protected Car createCar(String type) {
Car car = null;
if(type.equals("red")) {
System.out.println("小米出品");
return new RedCar();
} else if (type.equals("blue")) {
System.out.println("小米出品");
return new BlueCar();
}
return car;
}
}

Main:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.bestqiang.factory;

import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.CarStore;

/**
* @author BestQiang
*/
public class Main {
public static void main(String[] args) {
// 依赖于抽象类
CarStoreF carStore = new HuaweiCarStore();
Car blue = carStore.orderCar("blue");
Car red = carStore.orderCar("red");
System.out.println(blue);
System.out.println(red);
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
我是blue汽车, 我的价格是: 2000$,速度是:888km/s
蓝汽车可以开走了!
蓝汽车清洗完成了!
我是red汽车, 我的价格是: 1000$,速度是:999km/s
红汽车清洗完成了!
红汽车可以开走了!
Car{color='blue', price='2000$', speed='888km/s'}
Car{color='red', price='1000$', speed='999km/s'}

Process finished with exit code 0

抽象工厂模式

抽象工程模式: 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。

抽象工厂定义了一个接口,所有的具体工程都必须实现此接口,这个接口包含一组方法用来生产产品。
当要创建产品家族和想让制造的相关产品集合起来时,可以使用抽象工厂。

可以这样理解,现在汽车工厂只生产汽车,现在如果还想生产手机,再继承原来汽车的抽象类,复用抽象类的已有的方法,实现抽象方法,就不合适了。那就建立一个抽象工厂,而且把抽象工厂设置为接口,把所有涉及的产品都写进去,然后后面再实现这个接口。
又可以这样理解,抽象工厂比工厂模式高一个级别,抽象工厂在乎的是生产的汽车还是手机,而工厂模式在乎的是生产的手机是什么样子的。在确定生产什么以后,工厂模式往往隐含在抽象工厂中。

下图中新增一个手机类,然后使用抽象工厂进行创建。
img
实现代码如下:
Phone:

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
package com.bestqiang.AFactory;

/**
* @author BestQiang
*/
public abstract class Phone {
private int color;
private int price;

@Override
public String toString() {
return "Phone{" +
"color=" + color +
", price=" + price +
'}';
}

public int getColor() {
return color;
}

public void setColor(int color) {
this.color = color;
}

public int getPrice() {
return price;
}

public void setPrice(int price) {
this.price = price;
}

protected abstract void call();
}

HuaweiPhone:

1
2
3
4
5
6
7
8
9
10
11
package com.bestqiang.AFactory;

/**
* @author BestQiang
*/
public class HuaweiPhone extends Phone {
@Override
protected void call() {
System.out.println("华为,非一般的感觉!");
}
}

XiaomiPhone:

1
2
3
4
5
6
7
8
9
10
11
package com.bestqiang.AFactory;

/**
* @author BestQiang
*/
public class XiaomiPhone extends Phone {
@Override
protected void call() {
System.out.println("小米,永不止步!");
}
}

Factory:

1
2
3
4
5
6
7
8
9
10
11
package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.Car;

/**
* @author BestQiang
*/
public abstract class Factory {
public abstract Phone phoneFactory(String type);
public abstract Car carFactory(String type);
}

FactoryA:

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
package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/**
* @author BestQiang
*/
public class FactoryA extends Factory {


@Override
public Phone phoneFactory(String type) {
if(type.equals("huawei")) {
print();
return new HuaweiPhone();
} if (type.equals("XiaomiPhone")) {
print();
return new XiaomiPhone();
}
return null;
}

@Override
public Car carFactory(String type) {
if(type.equals("red")) {
print();
return new RedCar();
} if (type.equals("blue")) {
print();
return new BlueCar();
}
return null;
}

private void print() {
System.out.println("A工厂出品");
}
}

FactoryB:

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
package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/**
* @author BestQiang
*/
public class FactoryB extends Factory {

@Override
public Phone phoneFactory(String type) {
if(type.equals("huawei")) {
print();
return new HuaweiPhone();
} if (type.equals("XiaomiPhone")) {
print();
return new XiaomiPhone();
}
return null;
}

@Override
public Car carFactory(String type) {
if(type.equals("red")) {
print();
return new RedCar();
} if(type.equals("blue")) {
print();
return new BlueCar();
}
return null;
}

private void print() {
System.out.println("B工厂出品");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.Car;

/**
* @author BestQiang
*/
public class Main {
public static void main(String[] args) {
Factory factory = new FactoryA();
Car red = factory.carFactory("red");
System.out.println(red);
}
}

运行结果:

1
2
3
4
A工厂出品
Car{color='red', price='1000$', speed='999km/s'}

Process finished with exit code 0

三种工厂模式算是介绍完了,总结一下,

  • 简单工厂模式不能动态切换工厂,不依赖与抽象。
  • 工厂方法模式创建一个抽象的工厂类,子类进行继承实现,可以动态切换工厂,适合同一种类。
  • 抽象工厂模式把多个工厂隐含在里面,可以把相关的产品集合起来。是工厂模式的升级。
-------------本文结束感谢您的阅读-------------
愿你所有幸运,都不期而遇;愿你所有美好,都如约而至。