您的位置:首页 > 其它

设计模式之禅——模板方法模式&钩子方法

2016-08-21 12:15 267 查看
**

**板方法模式的定义:

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

例子:做一个简单的悍马车的模型

见UML图



一个抽象悍马模型类 HummerModel,然后有两个悍马具体型号的实现

类。见代码

public abstract class HummerModel {

//发动了
protected abstract void start();
//停下了
protected abstract void stop();
//喇叭发出声音了
protected abstract void alarm();
//引擎也开始响了
protected abstract void engineBoom();
public final void run(){
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}


public class HummerH1Model extends HummerModel {

@Override
protected void start() {
System.out.println("悍马H1发动");
}

@Override
protected void stop() {
System.out.println("悍马H1停车");
}

@Override
protected void alarm() {
System.out.println("悍马H1鸣笛");
}

@Override
protected void engineBoom() {
System.out.println("悍马H1引擎发出声响");
}

}


public class HummerH2Model extends HummerModel{

@Override
protected void start() {
System.out.println("悍马H2发动");
}

@Override
protected void stop() {
System.out.println("悍马H2停车");
}

@Override
protected void alarm() {
System.out.println("悍马H2鸣笛");
}

@Override
protected void engineBoom() {
System.out.println("悍马H2引擎发出声响");
}

}


ok,模板方法模式体现在哪里呢?注意它的定义:定义一个操作的算法的框架。很明显,抽象类中的run方法就是这个算法的框架,也就是模板。

模板方法模式就是如此简单~ 我们来看一下它的通用模板

public abstract class AbstractClass{
//基本方法
protected abstract void doSomething();
//基本方法
protected abstract void doAnything();
//模板方法
public final void tempeteMethod(){
this.doSomething();
this.doAnything();
}
}


public class ConcreteClass1 extends AbstractClass{
protected void doAnything(){
//逻辑处理
}
protected void doSomething(){
//逻辑处理
}
}


public class ConcreteClass2 extends AbstractClass{
protected void doAnything(){
//逻辑处理
}
protected void doSomething(){
//逻辑处理
}
}


模板方法模式的优点

封装不变的内容,扩展可变部分,如果我们要添加一个H3悍马模型,只需要继承父类就可以了。

提取公共部分代码,便于维护

行为由父类控制,子类实现。基本方法是由子类实现的,因此子类可以通过拓展的方法增加相应的功能,符合开闭原则。

模板方法模式的使用场景

多个子类有公有的方法,并且逻辑基本相同时

重复、复杂的算法,可以把核心算法设计为模板方法,周边的细节则有各个子类实现

代码重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后用钩子方法(见下面的”模板方法拓展“)约束其行为。

模板方法模式的拓展(钩子方法)

上面的代码有个问题,喇叭是默认响的,人不能控制,怎么完善呢?

注意!钩子方法应该是最开始设计就有的,而不是去完善、纠正错误的

public abstract class HummerModel {
//是否能发动
protected boolean isAlarm() {
return false;
}
//发动了
protected abstract void start();
//停下了
protected abstract void stop();
//喇叭发出声音了
protected abstract void alarm();
//引擎也开始响了
protected abstract void engineBoom();
public final void run(){
this.start();
this.engineBoom();
if(this.isAlarm()){
this.alarm();
}
this.stop();
}
}


public class HummerH1Model extends HummerModel {

private boolean alarmFlag = true;
public void setAlarm(boolean isAlarm){
alarmFlag = isAlarm;
}
@Override
protected boolean isAlarm(){
return this.alarmFlag;
}
@Override
protected void start() {
System.out.println("悍马H1发动");
}

@Override
protected void stop() {
System.out.println("悍马H1停车");
}

@Override
protected void alarm() {
System.out.println("悍马H1鸣笛");
}

@Override
protected void engineBoom() {
System.out.println("悍马H1引擎发出声响");
}

}


虽然这里有模板方法,但是通过钩子方法我们还是能够影响到模板方法的执行(不是影响它的逻辑)。钩子方法在我们平时的编程过程中也是非常常见的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息