一、模式定义
- 模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
- 设计原则
好莱坞原则,别调用我们,我们会调用你。
其中“我们”是指高层组件,如父类;“你”是指低层组件,如子类。 - 相关组件
- AbstractClass:抽象类,包含模板方法、钩子函数。模板方法一般是final的,不能由子类重新定义;钩子函数可被子类覆盖,一般可以用来控制父类中模板方法的逻辑。
- ConcreteClass:具体类,实现抽象的操作,当模板方法调用这些操作时,会由这个类的具体方法执行。
二、举例说明
- 场景:多个具体类有相似的操作步骤时,可以使用模板方法模式来保护这些算法。
- 具体需求:每个英雄都有QWER四个技能,假设只有W技能可能不会造成伤害,如亚索的W是风墙、盖伦的W是增加双抗、剑圣的W是回血。现需要演示英雄的伤害技能,如果W技能不能造成伤害,则不参与演示。提供一个统一的接口,来调用此接口的方法释放各英雄的伤害技能。
三、代码实现
- 英雄节能抽象类
public abstract class AbstractHeroSkill { public final void harmSkill() { skillQ(); if (hook()) { skillW(); } skillE(); skillR(); } public abstract void skillQ(); public abstract void skillW(); public abstract void skillE(); public abstract void skillR(); /** * 钩子函数:子类可覆盖这个方法,来控制模板方法中的逻辑 * * @return */ public boolean hook() { return true; } }
- 具体类:盖伦、小鱼人
public class Galen extends AbstractHeroSkill { @Override public void skillQ() { System.out.println("Q:致命打击"); } @Override public void skillW() { System.out.println("W:勇气"); } @Override public void skillE() { System.out.println("E:审判"); } @Override public void skillR() { System.out.println("R:德玛西亚正义"); } @Override public boolean hook() { System.out.println("盖伦的W技能不是伤害技能,无需释放!"); return false; } } public class Fizz extends AbstractHeroSkill { @Override public void skillQ() { System.out.println("Q:淘气打击"); } @Override public void skillW() { System.out.println("W:海石三叉戟"); } @Override public void skillE() { System.out.println("E:古灵/精怪"); } @Override public void skillR() { System.out.println("R:巨鲨强袭"); } }
- 开始演示
public static void main(String[] args) { AbstractHeroSkill galen = new Galen(); AbstractHeroSkill fizz = new Fizz(); System.out.println("盖伦的伤害技能演示..."); galen.harmSkill(); System.out.println("---------------------------"); System.out.println("小鱼人的伤害技能演示..."); fizz.harmSkill(); }
执行结果