java设计模式—模板方法模式
1.定义 : 定义一个操作中算法的框架,而去将一些步骤延迟到子类实现,使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤.说的有点高大上啊,简单来说是这样的,定义一个抽象类,这个类叫做抽象模板,它里面有两种方法: 1.模板方法,一般是一个具体的方法,也就是一个框架,一个算法,将其他方法进行调度,完成一些固定的逻辑. 2. 基本方法,也就是这些方法是抽象的应该由子类实现的.并且应该去让模板方法进行调度. 其他类就实现这个模板并定义一些具体的逻辑.
2.步骤及要点
1.定义一个抽象类作为具体模板,将算法调度作为一个或多个具体的实现方法定义,其他方法应由子类去实现.
2.定义具体的模板集成这个抽象模板,并完成具体的业务逻辑.
是不是很简单,是的,模板方法模式本来就不太难,它有着自己明显的特点,可能我们实际开发中用到过,但是我们不知道它是模板方法模式也有可能.
3.下面看具体实现.
(1) 通用实现(一般实现)
/**
* 这是抽象模板类
* @author psp
*
*/
public abstract class Car {
protected abstract void start();
protected abstract void stop();
protected abstract void engineBoom();
public final void run(){
start();
stop();
engineBoom();
}
}
/**
* 这是一个具体的模板类
* @author psp
*
*/
public class Benz extends Car {
protected void start() {
System.out.println("奔驰车启动了.");
}
protected void stop() {
System.out.println("奔驰车停止了.");
}
protected void engineBoom() {
System.out.println("奔驰车鸣笛.");
}
}
/**
* 这是另一个具体的模板类
* @author psp
*
*/
public class Bmw extends Car {
protected void start() {
System.out.println("宝马车启动了.");
}
protected void stop() {
System.out.println("宝马车停止了.");
}
protected void engineBoom() {
System.out.println("宝马车鸣笛.");
}
/**
* 这是一个测试类
*
* @author psp
*
*/
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
Car benz = new Benz();
Car bmw = new Bmw();
benz.run();
bmw.run();
}
}
需要注意的地方: 抽象模板类中模板方法一般设置为final类型,不允许被复写. 抽象模板类中的基本方法一般设置成protected 类型,子类尽量不要扩大其访问权限,这样也符合设计模式的迪米特法则.迪米特法则的原则是低耦合,弱耦合,又叫做最少知识原则.
模板方法实现后的优点:
- 封装不变的部分,扩展可变部分.
- 提取公共部分代码,便于维护
- 行为由父类控制,子类实现
(2)模板方法模式的扩展(带钩子函数的模板方法模式)
假如: 有一天,我们发现基本方法的调用是有条件的,也就是说,某个或某几个基本方法可能需要调用,也可能不需要调用,具体要看子类是否需要,假如需要改上这么一个需求,我们怎么办呢?我们是不是要哭了,不能,自己写的代码,含着泪也要改完.(不要想歪了…)这个其实也简单,加入一个钩子函数就行了,什么是钩子函数呢,其实这个函数就像我们平常开发中用到的变量控制,或者条件控制一样,只不过封装到一个方法里面了.下面看具体实现.假如现在我们不一定需要汽车鸣笛,是否需要鸣笛看子类自己想不想,由子类自己来控制.
/**
* 这是抽象模板类
*
* @author psp
*
*/
public abstract class Car {
protected abstract void start();
protected abstract void stop();
protected abstract void engineBoom();
public final void run() {
start();
if (isAlarm()) {
engineBoom();
}
stop();
}
/**
* 钩子函数
*
* @return 是否需要鸣笛,默认为true.
*/
protected boolean isAlarm() {
return true;
}
}
/**
* 这是一个具体的模板类
* @author psp
*
*/
public class Benz extends Car {
protected void start() {
System.out.println("奔驰车启动了.");
}
protected void stop() {
System.out.println("奔驰车停止了.");
}
protected void engineBoom() {
System.out.println("奔驰车鸣笛.");
}
/**
* 子类重写该方法,默认需要鸣笛
*/
protected boolean isAlarm() {
return true;
}
}
/**
* 这是另一个具体的模板类
* @author psp
*
*/
public class Bmw extends Car {
protected void start() {
System.out.println("宝马车启动了.");
}
protected void stop() {
System.out.println("宝马车停止了.");
}
protected void engineBoom() {
System.out.println("宝马车鸣笛.");
}
/**
* 子类重写该方法,默认不需要鸣笛
*/
protected boolean isAlarm() {
return false;
}
}