**模板方法模式:**在一个方法中定义一个算法的骨架,现将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
要点
- 模板方法定义了算法的步骤,把这些步骤的实现延迟到了子类。
- 模板方法模式为我们提供了一种代码复用的重要技巧。
- 模板方法的抽象类可以定义具体方法,抽象方法和钩子。
- 抽象方法由子类实现。
- 钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。
- 为了防止子类改变模板方法中的算法,可以将模板方法声明为final。
- 策略模式和模板方法模式都封装算法,一个用组合,一个用继承。
介绍
**意图:**定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
**主要解决:**一些方法通用,却在每一个子类都重新写了这一方法。
**何时使用:**有一些通用的方法。
**如何解决:**将这些通用算法抽象出来。
**关键代码:**在抽象类实现,其他步骤在子类实现。
应用实例: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
**缺点:**每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
**注意事项:**为防止恶意操作,一般模板方法都加上 final 关键词。
实现
package HeadFirstDesignMode.templatemethod;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 描述:模板方法模式
*/
public class TemplateMethodPattern {
public static void main(String[] args) {
TeaHook myTeaHook = new TeaHook();
CoffeeHook coffeeHook = new CoffeeHook();
myTeaHook.prepareRecipe();
System.out.println("开始喝茶...");
System.out.println();
coffeeHook.prepareRecipe();
System.out.println("开始喝咖啡...");
}
}
abstract class CaffeineBeverageWithHook {
final void prepareRecipe(){
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) addCondiments();
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("开始煮水");
}
void pourInCup(){
System.out.println("倒入杯中");
}
// 一个钩子
boolean customerWantsCondiments() {
return true;
}
protected String getUserInput() {
String answer = null;
System.out.println("要加调料吗?(y/n)");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException e) {
System.err.println("请检查你的输入!!");
}
return answer == null ? "n" : answer;
}
}
class TeaHook extends CaffeineBeverageWithHook {
@Override
void brew() {
System.out.println("开始泡茶");
}
@Override
void addCondiments() {
System.out.println("添加柠檬");
}
@Override
boolean customerWantsCondiments() {
String answer = getUserInput();
return "y".equalsIgnoreCase(answer);
}
}
class CoffeeHook extends CaffeineBeverageWithHook {
@Override
void brew() {
System.out.println("开始磨咖啡");
}
@Override
void addCondiments() {
System.out.println("添加糖和牛奶");
}
@Override
boolean customerWantsCondiments() {
String answer = getUserInput();
return "y".equalsIgnoreCase(answer);
}
}
标签:子类,void,System,模式,println,方法,模板
From: https://blog.51cto.com/u_11906056/6985094