设计模式-模板方法模式(Template Method Pattern)
一、定义
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
二、概念解释
所谓算法的框架可以理解为一个抽象的固定的规则,在已有的规则下可以有多种的实现方式,让不同的子类去实现这些特定的规则
三、场景
大多数游戏都会有boos战的设计,打boss的步骤可以简化为一个固定流程,移动到boss、攻击boss、获取奖励,但是不同的职业移动的方式、攻击的技能、得到的奖励各有不同,我就可以用不同的职业去实现我定义的打boss的这个流程
四、实现
1、类图
2、代码实现
首先定义一个打boss的抽象类 在这个类中定义一个固定的打boss规则
public abstract class BattleBoss {
/**
* 移动到boss
*/
protected abstract void moveBoss();
/**
* 释放技能
*/
protected abstract void releaseSkills();
/**
* boss爆装备
*/
protected abstract void getEquip();
/**
* 加上final 防止恶意操作 不允许子类覆写
*/
public final void attackBoss() {
moveBoss();
releaseSkills();
getEquip();
}
定义两个不同的职业分别实现自己打boss的固定规则
public class Mage extends BattleBoss{
@Override
protected void moveBoss() {
System.out.println("使用传送魔法移动到boss");
}
@Override
protected void releaseSkills() {
System.out.println("释放烈焰风暴攻击boss");
}
@Override
protected void getEquip() {
System.out.println("获取降魔法杖");
}
}
public class Warrior extends BattleBoss{
@Override
protected void moveBoss() {
System.out.println("使用野蛮冲锋移动到boss");
}
@Override
protected void releaseSkills() {
System.out.println("释放万剑归宗技能");
}
@Override
protected void getEquip() {
System.out.println("获取渴血战斧装备");
}
}
定义一个玩家 在这个游戏里可以有很多的角色 当然我也可以随时切换角色
public class Player {
private BattleBoss battleBoss;
public Player(BattleBoss battleBoss) {
this.battleBoss = battleBoss;
}
public void attackBoss() {
battleBoss.attackBoss();
}
public void changeProfession(BattleBoss battleBoss) {
this.battleBoss = battleBoss;
}
}
当我上线打算给不同的角色刷装备时
@SpringBootTest
public class TemplateMethodTest {
@Test
public void test() {
// 先操纵法师打boss
Player player = new Player(new Mage());
player.attackBoss();
// 再换个职业打boss
player.changeProfession(new Warrior());
player.attackBoss();
}
}
五、优缺点
优点
- 封装不变,扩展可变。定义不变的规则,具体实现由子类扩展
- 方便。抽取公共规则,便于维护
缺点
- 子类扩展实现了父类定义的抽象规则,也就是子类的执行结果影响了父类,如果项目较复杂,可能会对增加代码阅读难度