设计模式之模板方法模式

模板方法模式的定义

定义一个算法中的操作框架,而将一些步骤延迟到子类中。使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。

模板方法模式是一种行为型模式,它是一种很简单很容易理解的模式。

举个栗子

模板方法模式的模型图

类结构非常简单,编码也很简单

  • 抽象模板类
1
2
3
4
5
6
7
8
9
public abstract class AbstractClass {
protected abstract void operation1();
protected abstract void operation2();
//模板方法
public void templateMethod() {
operation1();
operation2();
}
}
  • 具体模板类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ConcreteClass1 extends AbstractClass {
@Override
protected void operation1() {
//实现
}
@Override
protected void operation2() {
//实现
}
}
public class ConcreteClass2 extends AbstractClass {
@Override
protected void operation1() {
//实现
}
@Override
protected void operation2() {
//实现
}
}
  • 调用场景
1
2
3
4
5
6
7
8
public class Client {
public static void main(String[] args) {
AbstractClass class1=new ConcreteClass1();
AbstractClass class2=new ConcreteClass2();
class1.templateMethod();
class2.templateMethod();
}
}

这样就实现了模板方法模式,在模板方法中,调用完全由模板方法完成。抽象模板中的基本方法尽量设计为protected类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected类型。实现类若非必要,尽量不要扩大父类中的访问权限。

适用范围

在多个子类有共有的方法,并且逻辑基本相同,或者可以有一个大的框架来实现核心逻辑,之类完成细枝末节的时候,模板方法是一种很好的选择。而且模板方法常常用来在重构的时候提取共有逻辑。

优点缺点

模板方法模式封装了不变的东西,把变化交给子类扩展,符合开闭原则,有利于系统维护。

模板方法模式的缺点是它改变了我们以往的编程思维方式,由子类实现来决定父类行为,可能会造成学习成本变高的问题。

注意事项

上面的例子有没有问题?如果我想只执行模板里面的一部分功能我们有办法控制吗?这时候上面的模型就产生了缺陷,于是产生了模板方法中另一个概念–钩子方法。

带有钩子方法的模板方法

首先来看我们在上面的例子中添加一个钩子方法,模型如下

修改的编码如下

  • 抽象模板类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class AbstractClass {
protected abstract void operation1();
protected abstract void operation2();
//模板方法
public void templateMethod() {
if (isHooked()){
operation1();
}
operation2();
}
//钩子方法
protected boolean isHooked(){
return true;
}
}
  • 具体模板类
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 ConcreteClass1 extends AbstractClass {
@Override
protected void operation1() {
//实现
}
@Override
protected void operation2() {
//实现
}
@Override
protected boolean isHooked() {
return false;
}
}
public class ConcreteClass2 extends AbstractClass {
@Override
protected void operation1() {
//实现
}
@Override
protected void operation2() {
//实现
}
}

调用场景不变。我们把在需要由子类控制的方法外添加了一层判断,由子类决定是否重写钩子方法来决定方法是否执行,这样就可以自由的控制调用,模板方法模式就健全了。

模板方法模式是一种极方便扩展的设计模式,很多开源框架的设计都采用了这种方式来实现扩展开发。

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!