🍀以下内容同步发布在我的个人博客https://www.lvjguo.top😊
1 介绍
定义:定义一个操作中的算法的骨架,并允许子类为一个或多个步骤提供实现。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
类型:行为型
适用场景:
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类实现
- 各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,增强复用性,便于维护。 3、行为由父类控制,子类实现。
缺点:1、每一个不同的实现都需要一个子类来实现,导致类的个数增加,增加了系统实现的复杂度。2、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改变。
相关设计模式:
- 工厂方法模式是模板方法模式的一种特殊形式。 同时, 工厂方法可以作为一个大型模板方法中的一个步骤。
- 策略模式基于组合机制: 你可以通过对相应行为提供不同的策略来改变对象的部分行为。 模板方法在类层次上运作, 因此它是静态的。 策略在对象层次上运作, 因此允许在运行时切换行为。而模板方法基于继承机制: 它允许你通过扩展子类中的部分内容来改变部分算法。
UML类图:
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
2 示例
我们在学习时,经常会看根据课程学习,课程的制作需要准备PPT,手记,图片素材或者视频等等,但是因为课程的性质不同,在制作过程中所要准备的东西也不同,有的需要图片素材或者手记,有的则不需要。那么我们怎么利用模板方法模式进行实现呢?
- 抽象类(AbstractClass)
/**
* 抽象类定义了一个模板方法,其中通常会包含某个由抽象原语操作调用组成的算
* 法框架。具体子类会实现这些操作,但是不会对模板方法做出修改。
*/
public abstract class ACourse {
// 模板方法定义了某个算法的框架。
protected final void makeCourse(){
this.makePPT();
this.makeVideo();
if(needWriteArticle()){
this.writeArticle();
}
this.packageCourse();
}
// 某些步骤可在基类中直接实现。
final void makePPT(){
System.out.println("制作PPT");
}
void makeVideo(){
System.out.println("制作视频");
}
final void writeArticle(){
System.out.println("编写手记");
}
//钩子方法
protected boolean needWriteArticle(){
return false;
}
// 某些可定义为抽象类型。
abstract void packageCourse();
}
- 具体类(ConcreteClass)
// 具体类必须实现父类中的所有抽象操作,但是它们不能重写模板方法自身。
public class JavaCourse extends ACourse {
@Override
void packageCourse() {
System.out.println("提供课程Java源代码");
}
//重写钩子方法
@Override
protected boolean needWriteArticle() {
return true;
}
}
public class FECourse extends ACourse {
private boolean needWriteArticleFlag = false;
@Override
void packageCourse() {
System.out.println("提供课程的前端代码");
System.out.println("提供课程的图片等多媒体素材");
}
public FECourse(boolean needWriteArticleFlag) {
this.needWriteArticleFlag = needWriteArticleFlag;
}
@Override
protected boolean needWriteArticle() {
return this.needWriteArticleFlag;
}
}
- Client类
public class Client {
public static void main(String[] args) {
System.out.println("后端设计模式课程start---");
ACourse designPatternCourse = new DesignPatternCourse();
designPatternCourse.makeCourse();
System.out.println("后端设计模式课程end---");
System.out.println("前端课程start---");
ACourse feCourse = new FECourse(false);
feCourse.makeCourse();
System.out.println("前端课程end---");
}
}
运行结果:
后端设计模式课程start---
制作PPT
制作视频
编写手记
提供课程Java源代码
后端设计模式课程end---
前端课程start---
制作PPT
制作视频
提供课程的前端代码
提供课程的图片等多媒体素材
前端课程end---