模板方法模式
模板方法模式是一种较为常见的行为型设计模式,其理念就是在父类中规定代码框架,而具体的实现在子类中完成
我们假设一个场景:现在你有一辆摩托车,你要骑着它出去。
public class Motocycle {
public void drive() {
boarding();
fire();
gun();
go();
}
private void go() {
System.out.println(this.getClass().getSimpleName() + " go");
}
private void gun() {
System.out.println("Twist the handlebar");
}
private void fire() {
System.out.println("Step on the pedal");
}
private void boarding() {
System.out.println("Sitting on the motorcycle");
}
public static void main(String[] args) {
Motocycle motocycle = new Motocycle();
motocycle.drive();
}
}
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
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
场景更改:现在你买了一辆小汽车,你也要开着它出去
public class Car {
public void drive() {
boarding();
fire();
gun();
go();
}
private void go() {
System.out.println(this.getClass().getSimpleName() + " go");
}
private void gun() {
System.out.println("Step on the gas pedal");
}
private void fire() {
System.out.println("Screw the key");
}
private void boarding() {
System.out.println("Sitting in the car");
}
public static void main(String[] args) {
Car car = new Car();
car.drive();
}
}
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
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
emmm......貌似是可以的,但是好像有一些重复代码是没必要写两遍的
- drive方法
- go方法
开车的过程虽然细节大不相同,但是步骤是一样的,重构后的代码如下
public abstract class AbstractTransportation {
public final void drive() {
boarding();
fire();
gun();
go();
}
protected abstract void gun();
protected abstract void fire();
protected abstract void boarding();
private void go() {
System.out.println(this.getClass().getSimpleName() + " go");
}
}
public class Motocycle extends AbstractTransportation{
@Override
protected void gun() {
System.out.println("Twist the handlebar");
}
@Override
protected void fire() {
System.out.println("Step on the pedal");
}
@Override
protected void boarding() {
System.out.println("Sitting on the motorcycle");
}
public static void main(String[] args) {
Motocycle motocycle = new Motocycle();
motocycle.drive();
}
}
public class Car extends AbstractTransportation {
@Override
protected void gun() {
System.out.println("Step on the gas pedal");
}
@Override
protected void fire() {
System.out.println("Screw the key");
}
@Override
protected void boarding() {
System.out.println("Sitting in the car");
}
public static void main(String[] args) {
Car car = new Car();
car.drive();
}
}
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
60
61
62
63
64
65
66
67
68
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
60
61
62
63
64
65
66
67
68
可以看到,我们将开车的drive方法上移至抽象类,go方法由于是一样的,所以也进行上移。更改后的代码更加的间接明了了
总结
模板方法模式类图如下
一个抽象类规定步骤,由子类具体实现
模板方法模式有什么优点呢?最明显的,模板方法模式将不变的行为移到父类,减少了代码。其次,由子类来实现算法的某些细节,有助于业务的扩展
实际使用场景
在很多优秀的程序中都可以见到模板方法模式,接下来就举一个在jdk源码中的实例加以讲解
//AbstractQueuedSynchronizer#acquire
//tryAcquire方法交由子类实现
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
如上文代码,在抽象类中规定要请求就必须先执行tryAcquire方法,并在tryAcquire中抛出异常,所以子类必须实现tryAcquire方法,否则就无法使用acquire方法。