示例
当我们设计一个类时,我们能明确它对外提供的某个方法的内部执行步骤,
但一些步骤,不同的子类有不同的行为时,我们该如何来设计该类?
下面以玩王者荣耀为例展开学习:
玩游戏首先需要初始化游戏,然后加载地图、加载角色、然后才能开始游戏,最后结束游戏
定义一个Game类:
public abstract class Game {
public final void play () {
initialize();
loadMap();
loadRole();
startPlay();
endPlay();
}
/** 初始化游戏 */
protected abstract void initialize();
/** 加载地图 */
protected abstract void loadMap();
/** 加载角色 */
protected abstract void loadRole();
/** 开始游戏 */
protected abstract void startPlay();
/** 结束游戏 */
protected abstract void endPlay();
}
上面类的实现类:
public class KingGlory extends Game {
@Override
protected void initialize() {
System.out.println("王者荣耀正在初始化,请稍后。。。");
}
@Override
protected void loadMap() {
System.out.println("正在加载王者峡谷地图。。。");
}
@Override
protected void loadRole() {
System.out.println("正在加载角色鲁班七号。。。");
}
@Override
protected void startPlay() {
System.out.println("开始玩王者荣耀。。。");
}
@Override
protected void endPlay() {
System.out.println("结束王者荣耀游戏,保存数据。。。");
}
}
测试类:
public class Test {
public static void main(String[] args) {
Game game = new KingGlory();
game.play();
}
}
模板方法模式
定义
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
意图
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决问题
一些方法通用,却在每一个子类都重新写了这一方法
适用场景
1、有多个子类共有的方法,且逻辑相同。
2、重要的、复杂的方法,可以考虑作为模板方法
优缺点
优点:
1、封装不变部分,扩展可变部分。
2、提取公共代码,便于维护。
3、行为由父类控制,子类实现。
缺点:
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞
类图:
涉及的角色:
- 抽象模板(AbstractTemplate)角色:定义了一个或多个抽象操作,以便让子类实现,这些抽象操作叫基本操作,它们是*逻辑的组成步骤;定义并实现了一个模板方法,这个模板方法一般是一个具体方法,它给出了一个*逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现
- 具体模板(ContrateTemplate)角色:实现父类所定义的一个或多个抽象方法,它们是一个*逻辑的组成步骤;每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现,从而使得*逻辑的实现各不相同
对应源码:
public abstract class AbstractTemplate {
public void templateMethod() {
doOperation1();
doOperation2();
doOperation3();
}
/** 基本方法,由子类实现 */
protected abstract void doOperation1();
/** 基本方法,由子类实现 */
protected abstract void doOperation2();
/** 基本方法,已经实现 */
private final void doOperation3(){
//do something......
}
}
public class ContrateTemplate extends AbstractTemplate {
@Override
protected void doOperation1() {
System.out.println("doOperation1......");
}
@Override
protected void doOperation2() {
System.out.println("doOperation2......");
}
}
西天取经的九九八十一难
在《西游记》中,唐僧到西天取经途中所经历的八十一难,说到底,是观音菩萨所控制的一个项目,下面以上面场景为例,写一个小例子:
取经人所经历的劫难,每一步都是菩萨控制好的:
public abstract class LearnFromPeople {
public final void westernCountry() {
firstHard();
secondHard();
thirdHard();
}
/** 第一难 */
protected abstract void firstHard();
/** 第二难 */
protected abstract void secondHard();
/** 第三难 */
protected abstract void thirdHard();
}
唐僧去西天取经,继承了取经人这个抽象类,然后需要历经81难:
public class TangMonk extends LearnFromPeople {
@Override
protected void firstHard() {
System.out.println("金蝉遭贬第一难");
}
@Override
protected void secondHard() {
System.out.println("出胎几杀第二难");
}
@Override
protected void thirdHard() {
System.out.println("满月抛江第三难");
}
}
唐僧开始上路了:
public class Test {
public static void main(String[] args) {
LearnFromPeople people = new TangMonk();
people.westernCountry();
}
}
需要注意的是,为了防止恶意的操作,模板方法上面都会加上final关键字