模板方法
2018-05-10 本文已影响0人
Crazy贵子
模板方法
定义
定义一个操作中的算法的框架,将一些步骤延迟到子类中,是的子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
通用类图
通用类图.png模板方法仅使用了继承关系,其中AbstractClass是抽象类,其中有两种方法:
- 基本方法
这个由子类具体实现,被模板方法所调用
- 模板方法
可以有一个,也可以有多个,是算法的具体框架,完成相应的逻辑。为了防止恶意的操作,一般模板方法都声明为final
类型
通用代码
// 定义基本方法和模板方法
public abstract class AbstractClass {
protected abstract void doSomething();
protected abstract void doAnything();
public final void templateMethod(){ // 实现算法框架
doSomething();
doAnything();
}
}
// 子类1
public class ConcreteClass1 extends AbstractClass {
@Override
protected void doSomething() {
}
@Override
protected void doAnything() {
}
}
// 子类2
public class ConcreteClass2 extends AbstractClass {
@Override
protected void doSomething() {
}
@Override
protected void doAnything() {
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass1();
abstractClass.templateMethod();
}
}
子类负责实现特定算法中的具体逻辑,但是不会影响整个算法的框架。
样例展示
这次我们拿建房子来说明,房子有大概有多种建法,但是基本都脱离不了打基地、砌墙和封顶这几个操作吧,而且这个顺序基本是固定的,所以我们可以将这三个动作定义为基本方法,然后定义一个模板方法完成框架的搭建。
样例展示.pngpublic abstract class BuildHouse {
protected abstract void layTheFoundations(); // 打地基
protected abstract void buildAWall(); // 砌墙
protected abstract void capping(); // 封顶大吉
public final void build() {
layTheFoundations();
buildAWall();
capping();
}
}
房子类型1
public class House1 extends BuildHouse {
@Override
protected void layTheFoundations() {
System.out.println("水泥基地");
}
@Override
protected void buildAWall() {
System.out.println("水泥墙");
}
@Override
protected void capping() {
System.out.println("水泥天花板");
}
}
房子类型2
public class House2 extends BuildHouse {
@Override
protected void layTheFoundations() {
System.out.println("水泥基地");
}
@Override
protected void buildAWall() {
System.out.println("水泥墙");
}
@Override
protected void capping() {
System.out.println("木板天花板");
}
}
客户端调用
public class Client {
public static void main(String[] args) {
BuildHouse house = new House1();
house.build();
}
}
实现很简单,调用也很简单,因为整体框架就是这样的,只需要木板方法就可以了。相应的,如果需要简单修改模板方法的框架也是可以的,比如说有些特殊的子类不需要实现其中的某一项,那么我们可以提供一个借口给子类实现。假设现在某种房子不用砌墙,那么这样子修改就可以了。
public final void build() {
layTheFoundations();
if (isBuildAWall()) {
buildAWall();
}
capping();
}
protected boolean isBuildAWall() { // 提供修改借口,默认要砌墙
return true;
}
// 子类自己实现
private boolean isBuildAWall;
public void setBuildAWall(boolean buildAWall) {
isBuildAWall = buildAWall;
}
@Override
protected boolean isBuildAWall() {
return isBuildAWall;
}
// 客户端调用
BuildHouse house = new House2();
((House2) house).setBuildAWall(false);
house.build();
本文为《设计模式之禅》读后笔记总结