模板方法模式(学习笔记2021-08-06)
前言:
在模板方法模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
**意图:**定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
**主要解决:**一些方法通用,却在每一个子类都重新写了这一方法。
**何时使用:**有一些通用的方法。
**如何解决:**将这些通用算法抽象出来。
**关键代码:**在抽象类实现,其他步骤在子类实现。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
**缺点:**每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
**注意事项:**为防止恶意操作,一般模板方法都加上 final 关键词。
前提条件:
例如: 我们有二台游戏机, 其中一台是电脑、 一台是
switch
, 里面的游戏各不相同电脑动作是: 打开电源、 打开怪物猎人游戏、 进行游玩对应怪物猎人游戏、关闭电源。
switch
动作是: 打开电源、 打开天使猎魔女游戏、 进行游玩对应天使猎魔女游戏、关闭电源。
对应电脑与switch
类
public class Computer {
public void computerEntertainment(){
openPowerSupply();
openMonsterHunterGame();
playMonsterHunterGame();
closePowerSupply();
}
public void openPowerSupply(){
System.out.println("打开了电源");
}
public void openMonsterHunterGame(){
System.out.println("打开了怪物猎人游戏");
}
public void playMonsterHunterGame(){
System.out.println("游玩对应怪物猎人游戏");
}
public void closePowerSupply(){
System.out.println("关闭电源");
}
}
----------------------------Switch-----不同点-------------------------------
public void switchEntertainment(){
openPowerSupply();
openMonsterHunterGame();
playMonsterHunterGame();
closePowerSupply();
}
public void openAngelHuntingWitchGame(){
System.out.println("打开了天使猎魔女游戏");
}
public void playAngelHuntingWitchGame(){
System.out.println("游玩对应天使猎魔女游戏");
}
然后我们发现他们的其中某二个方法都是相同的可以抽取成为一个基类
基类
public abstract class OperationBase {
public void openPowerSupply(){
System.out.println("打开了电源");
}
public void closePowerSupply(){
System.out.println("关闭电源");
}
}
--------------------------------------------
然后
Computer
与Switch
继承基类 ,public class Switch extends OperationBase
测试
@Test
public void applicationTest() throws Exception {
Computer computer = new Computer();
Switch Switch = new Switch();
computer.computerEntertainment();
Switch.switchEntertainment();
}
//--------------------------------------
打开了电源
打开了怪物猎人游戏
游玩对应怪物猎人游戏
关闭电源
打开了电源
打开了天使猎魔女游戏
游玩对应天使猎魔女游戏
关闭电源
到这, 我们是不是他们还是有共同点的, 都是打开游戏(只是打开的游戏不同), 都是游玩游戏(只是游玩的游戏不同)
下面就是正式开始使用模板模式了
1.0 改造基类成为模板模式
public abstract class OperationBase {
/**
* 通用方法标记final, 不允许子类重写自定义
*/
public final void entertainment(){
openPowerSupply();
openGame();
playGame();
closePowerSupply();
}
/**
* 抽象打开与游玩游戏动作, 打开与游玩什么游戏由子类决定
*/
public abstract void openGame();
public abstract void playGame();
public final void openPowerSupply(){
System.out.println("打开了电源");
}
public final void closePowerSupply(){
System.out.println("关闭电源");
}
}
1.1 子类改造, 定义操作模板方法
public class Computer extends OperationBase{
@Override
public void openGame() {
System.out.println("打开了怪物猎人游戏");
}
@Override
public void playGame() {
System.out.println("游玩对应怪物猎人游戏");
}
}
//-------------------------------Switch同理---------------------------------------`
1.2 定义模板
public abstract class OperationTemplate {
/**
* 执行模板方法
*
* @param base
* @author: ZhiHao
* @date: 2021/8/6
*/
public static void executor(OperationBase base){
base.entertainment();
}
}
1.3 测试
@Test
public void applicationTest()throws Exception {
OperationTemplate.executor(new Computer());
OperationTemplate.executor(new Switch());
}
//---------------------------------------
打开了电源
打开了怪物猎人游戏
游玩对应怪物猎人游戏
关闭电源
打开了电源
打开了天使猎魔女游戏
游玩对应天使猎魔女游戏
关闭电源
到此我们就实现了一个模板方法, 后续在来其他游戏设备也能很好的扩展, 只需实现我们的基类模板, 打开与游玩什么游戏由子类决定,
模板方法就是将类似的动作更加进行抽象化了。 抽象化, 打开游戏动作 (打开什么由子类决定)
模板方法同时一些通用方法定义好, 并不允许被人修改, 逼迫别人必须使用模板中的实现方法。
模板方法并且调用全部都是由模板方法进行调用, 子类只做实现动作并不调用