设计模式学习——模板方法模式
一、什么是模板方法模式
模板方法模式:定义一个操作的算法的框架,将一些步骤延迟到子类中,从而使得子类在不改变整体算法结构的基础上即可重新定义该算法某些特点步骤。其类图如下:
从类图我们可以看出来模板方法非常简单,它仅仅利用了继承机制,其中AbstractClass为抽象模板,他的方法分两类:
基本方法
基本方法也叫基本操作,是由子类实现的方法,并在模板方法中被调用。
模板方法
可以有一个或多个,其主要实现对基本方法的调度,完成固定逻辑。
PS:为了防止模板方法被恶意修改,一般会给模板方法加上final关键字
二、模板方法的应用
接下来我们通过一个简单的例子说明此模式的使用。
我们设计了一款游戏,在此游戏中玩家可以选择将自己的角色切换为不同职业,不同职业的移动、攻击方式不同,但是其组合攻击技的流程是一样的,都需要释放远程技能,然后移动到目标处,最后释放近战技能。
我们首先设计抽象模板:
public abstract class ComboAttackTemplate { /** * 移动到目标处 */ protected abstract void move(); /** * 远程攻击 */ protected abstract void rangeAttack(); /** * 近身攻击 */ protected abstract void meleeAttack(); public void attack() { rangeAttack(); move(); meleeAttack(); } }
解下来我们分别实现法师和弓箭手对应的实现类:
/** * 法师组合攻击技 */ public class CharmerComboAttack extends ComboAttackTemplate { @Override protected void move() { System.out.println("闪现"); } @Override protected void rangeAttack() { System.out.println("火球术"); } @Override protected void meleeAttack() { System.out.println("法杖抡击"); } } /** * 弓箭手组合攻击技 */ public class ArcherComboAttack extends ComboAttackTemplate { @Override protected void move() { System.out.println("前滚翻"); } @Override protected void rangeAttack() { System.out.println("万箭齐发"); } @Override protected void meleeAttack() { System.out.println("匕首凿击"); } }
同理,我们可以设计出战士、刺客的组合攻击技。
三、模板方法优缺点
1、模板方法的优点
-
封装不变不分、扩展可变部分;
-
提取公共部分代码、方便维护;
-
行为由父类控制,子类实现。
2、模板方法的缺点
-
对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。
-
父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
-
由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍
四、模板方法应用场景
1、多个子类有公有的方法,并且逻辑基本相同时;
2、重要复杂的算法,可以把核心算法设计成模板,相关细节由子类实现;
3、项目重构时,模板方法也是常用的方式,将相同代码抽取到父类中,然后通过钩子函数约束其行为。