模版方法设计模式(Template)

Posted by 余腾 on 2019-08-21
Estimated Reading Time 5 Minutes
Words 1.3k In Total
Viewed Times

什么是模版方法设计模式?

模版方法设计模式—> 行为型模式

基本介绍

  • 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern), 在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
  • 简单说,模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。

模板方法模式的注意事项和细节

  • 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改;
  • 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用;
  • 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现;
  • 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大;
  • 一般模板方法都加上 final 关键字,防止子类重写模板方法;
  • 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤,这一系列的步骤基本相同,但其 个别步骤在实现时可能不同,通常考虑用模板方法模式来处理,强调的是步骤。

角色定义

  • AbstractClass 抽象类,类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现它的抽象方法 —> operation;
  • ConcreteClass 实现抽象方法 Operation,以完成算法中特点子类的步骤。

模版方法设计模式应用实例

  • 制作豆浆的流程:选材准备 —> 子类添加不同的材料 —> 浸泡 —> 打碎
  • 通过添加不同的配料,可以制作出不同口味的豆浆;
  • 选材准备、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的;


模版抽象类

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
//抽象类,表示制作豆浆的流程
public abstract class SoyaMilk {

//模版方法,final 不让子类覆盖
final void make() {
select();
addCondiments();
soak();
beat();
}

void select() {
System.out.println("1、选材准备");
}

//抽象方法,子类去实现,添加不同的配料
abstract void addCondiments();

//浸泡
void soak() {
System.out.println("3、浸泡");
}

//打碎
void beat() {
System.out.println("4、放入豆浆机打碎");
}
}

花生豆浆

1
2
3
4
5
6
public class PeanutSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
System.out.println("2、放入花生 ");
}
}

红豆豆浆

1
2
3
4
5
6
public class RedBeanSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
System.out.println("2、放入红豆 ");
}
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Client {
public static void main(String[] args) {
System.out.println("----制作红豆豆浆----");
SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
redBeanSoyaMilk.make();

System.out.println("----制作花生豆浆----");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}

//TODO
----制作红豆豆浆----
1、准备
2、放入红豆
3、浸泡
4、放入豆浆机打碎
----制作花生豆浆----
1、准备
2、放入花生
3、浸泡
4、放入豆浆机打碎

钩子方法

  • 在模板方法模式的父类中,可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”。
  • 比如,还是制作纯豆浆,不添加任何的配料,使用钩子方法对前面的模板方法进行改造。


模版抽象类 Hook

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
//抽象类,表示制作豆浆的流程
public abstract class SoyaMilk {

//模版方法,final 不让子类覆盖
final void make() {

select();
if (customerWantCondiments()) {
addCondiments();
}
soak();
beat();

}

void select() {
System.out.println("1、选材准备");
}

//抽象方法,子类去实现,添加不同的配料
abstract void addCondiments();

//浸泡
void soak() {
System.out.println("3、浸泡");
}

//打碎
void beat() {
System.out.println("4、放入豆浆机打碎");
}

//钩子方法,判断是否添加配料
boolean customerWantCondiments() {
return true;
}
}

纯豆浆 Hook

1
2
3
4
5
6
7
8
9
10
11
12
public class PureSoyaMilk extends SoyaMilk {

@Override
void addCondiments() {
}

@Override
boolean customerWantCondiments() {
System.out.println("2、不添加配料,制造纯豆浆");
return false;
}
}

红豆豆浆

1
2
3
4
5
6
7
8
9
10
11
public class RedBeanSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
System.out.println("2、放入红豆 ");
}

@Override
boolean customerWantCondiments() {
return true;
}
}

Client Hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Client {
public static void main(String[] args) {

System.out.println("----制作红豆豆浆----");
SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
redBeanSoyaMilk.make();

System.out.println("----制作纯豆浆----");
SoyaMilk pureSoyaMilk = new PureSoyaMilk();
pureSoyaMilk.make();
}
}

//TODO
----制作红豆豆浆----
1、选材准备
2、放入红豆
3、浸泡
4、放入豆浆机打碎
----制作纯豆浆----
1、选材准备
2、不添加配料,制造纯豆浆
3、浸泡
4、放入豆浆机打碎

模版方法模式在Spring框架中的应用

  • Spring IOC 容器初始化时运用到的模版模式。
    • refresh(); 模版方法
  • 钩子方法
    • postProcessBeanFactory();
    • onRefresh();

感谢阅读


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !