模版方法模式
模版方法模式的定义是定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。其实在我们日常编程中经常不自觉地就使用到了模版方法模式,但是很多情况下,我们并不知道自己使用了模版方法模式。
模式组成
模版方法模式的通用类图:
角色 | 关系 | 作用 |
---|---|---|
AbstractClass(抽象模版) | 具体模版的父类 | 其方法分为基本方法和模版方法 |
ConcreteClass(具体模版) | 抽象模版的子类 | 实现父类所定义的一个或多个抽象方法 |
在这里需要了解抽象模版中的两个方法类型:
- 基本方法:也叫基本操作,是由子类实现的父类,并在模版方法被调用
- 模版方法:可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑
表述代码
抽象模版类:
public abstract class AbstractClass {
//基本方法
protected abstract void doSomething();
//基本方法
protected abstract void doAnything();
//模版方法
public void templateMethod() {
/**
* 调用基本方法,完成相关逻辑
*/
this.doAnything();
this.doSomething();
}
}
具体模版类:
public class ConcreteClass1 extends AbstractClass {
@Override
protected void doSomething() {
// TODO Auto-generated method stub
System.out.println("dosometing1");
}
@Override
protected void doAnything() {
// TODO Auto-generated method stub
System.out.println("doanyting1");
}
}
public class ConcreteClass2 extends AbstractClass {
@Override
protected void doSomething() {
// TODO Auto-generated method stub
System.out.println("dosometing 2");
}
@Override
protected void doAnything() {
// TODO Auto-generated method stub
System.out.println("doanyting 2");
}
}
实现我们的业务类:
public class Client {
public static void main(String[] args) {
AbstractClass class1 = new ConcreteClass1();
AbstractClass class2 = new ConcreteClass2();
//调用模版方法
class1.templateMethod();
class2.templateMethod();
}
}
执行结果:
doanyting1
dosometing1
doanyting 2
dosometing 2
注意事项
- 为防止恶意操作,一般模版方法都会加上final关键字,不允许被覆写
- 抽象模版中的基本方法尽量设计为protected,符合迪米特法则,不需要暴露的属性和方法尽量不要设置为protected类型。实现类若非有必要,尽量不要夸大父类中的访问权限
优点
- 封装不变部分,扩展可变部分
- 提取公共部分代码,便于维护
- 行为由父类控制,父类实现
缺点
抽象类定义部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂项目中会带来代码阅读难度
使用场景
- 多个子类由公共的方法,并且逻辑基本相同时
- 重要、复杂的算法,可以把核心算法设计为模版方法,周边的相关细节功能则有各个子类实现
- 重构时,模版方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为