目录
一、概念
二、角色设计
三、代码实现
案例一
案例二
四、总结
一、概念
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类当中,使得子类可以不改变该算法结构的情况下重定义该算法的特定步骤,即在一个抽象类中公开定义了执行某一方法的模板,然后子类可以按需重写方法实现自己特有的逻辑。
通俗的来讲其实就好比做一道菜一样,同样的步骤每个人做出来的味道缺大相径庭,这个步骤就可以理解为模板方法模式,采用固定的步骤去做,但是如何去实现就看自己怎么想了。
二、角色设计
角色 | 描述 |
---|---|
AbstractClass(基类) | 抽象类,在基类中定义或声明了一系列基本操作,这些操作可以是具体或者是者抽象的,每一个操作都对应算法的一个步骤,这些步骤在其派生类中都可以重定义。基类规定了算法的流程框架,模板方法由基类定义或声明的一系列基本操作按照一定流程实现。 |
BraisedFish(派生类) | 实现在基类中声明的抽象方法,也可以覆盖在基类中已经实现的方法。 |
三、代码实现
案例一
假设做一盘菜固定有3个步骤,分别是热锅、烹饪和出锅,因为步骤是固定的,只有烹饪手法不同,只需要重写cooking方法即可。
1、定义一个抽象模板类
注:为了防止恶意的操作,一般模板方法前面会加上final关键字,不允许被覆写。
public abstract class AbstractClass {
final void operation(){
this.start();
this.cooking();
this.end();
}
private void start(){
System.out.println("热锅...");
}
protected abstract void cooking();
private void end(){
System.out.println("出锅...");
}
}
2、具体模板实现类
public class BraisedFish extends AbstractClass{
@Override
protected void cooking() {
System.out.println("做红烧肉...");
}
}
3、场景测试类
public static void main(String[] args) {
AbstractClass abstractClass = new BraisedFish();
abstractClass.operation();
}
4、运行结果
案例二
假设做一杯奶茶有三个固定的步骤,分别是选材、加料和打包,这边也同样采用相同的逻辑进行实现。
1、定义制作奶茶的抽象类
public abstract class MakeTeaMilk {
final void make(){
select();
addCondiments();
pack();
}
/**
* 选果茶/奶茶
*/
abstract void select();
/**
* 添加配料
*/
abstract void addCondiments();
/**
* 打包
*/
private void pack(){
System.out.println("奶茶打包!");
}
}
2、制作一杯果茶
/**
* 果茶
* @author HTT
*/
public class FruitTeaMilk extends MakeTeaMilk{
@Override
void select() {
System.out.println("选取柠檬汁");
}
@Override
void addCondiments() {
System.out.println("添加补丁");
}
}
3、测试
public static void main(String[] args) {
MakeTeaMilk fruitTeaMilk = new FruitTeaMilk();
fruitTeaMilk.make();
}
4、运行结果
四、总结
优点:
1、封装不变的部分,拓展可变的部分
2、提取公共代码,便于维护
3、行为由父类控制,由子类实现
主要用于多个子类共用的方法且逻辑相同的情况下使用。