前言

模板方法是本人认为23种设计模式最简单的。其根本就是巧妙运用java的继承机制,下面为大家以一一讲来.

什么是模板方法模式

定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定逻辑。

UML类图

图片描述

父类中具有两种方法,一种是基本方法,供子类复写,另一种是模板方法,用来调度基本方法,相当于定义一个框架。子类通过复写基本方法,调用父类的模板方法就是模板方法的体现。

使用场景

  1. 子类具有相同的方法,并且逻辑基本相同
  2. 代码重构时,模板方法会经常使用到,然后通过钩子函数(见模板方法扩展)约束其行为。

代码分析

public abstract class AbstractDoctor {

    //了解病情
    protected abstract void knowAboutSymptoms();
    //分析病情
    protected abstract void analysisIllness();
    //治疗患者
    protected abstract void curePatient();
        
    public void work() {
        knowAboutSymptoms();
        analysisIllness();
        curePatient();
    }
}
public class ChineseDoctor extends AbstractDoctor {

    @Override
    protected void knowAboutSymptoms() {
        System.out.println("中医通过望闻问切了解病人病情");
    }
    @Override
    protected void analysisIllness() {
        System.out.println("得知病情后,通过自己丰富的经验分析病情,制定治疗方案");
    }
    @Override
    protected void curePatient() {
        System.out.println("根据治疗方案给你抓中药");
    }
}
public class WestDoctor extends AbstractDoctor {
    @Override
    protected void knowAboutSymptoms() {
        System.out.println("简单询问,就让你去拍个片");
    }

    @Override
    protected void analysisIllness() {
        System.out.println("根据x光片,分析病人病情,制定治疗方案");
    }

    @Override
    protected void curePatient() {
        System.out.println("打针,输液,药片各来一打,包治百病");
    }
}
public class Client {


    public static void main(String[] args) {
        AbstractDoctor chineseDoctotr = new ChineseDoctor();
        chineseDoctotr.work();

        System.out.println("===============华丽的分隔符========================");

        AbstractDoctor westDoctor = new WestDoctor();
        westDoctor.work();

    }
}

测试结果:
中医通过望闻问切了解病人病情
得知病情后,通过自己丰富的经验分析病情,制定治疗方案
根据治疗方案给你抓中药
===============华丽的分隔符========================
简单询问,就让你去拍个片
根据x光片,分析病人病情,制定治疗方案
打针,输液,药片各来一打,包治百病

不管你是中医还是西医,你的工作就是治病救人,工作流程也基本相同,都是了解病情,分析病情,治疗病人这个流程。在父类中定义一个算法来控制流程,具体实现交给具体子类,再由子类调用父类的work(模板方法)进行运作。

模板方法模式的扩展

要知道,直到今天医疗资源也是很宝贵的资源。有的病人装病,有的人送到医院已经完全死去没有生命象征,对于这些病人我们就没有必要再去治疗了。那如何去控制呢?我们可以通过钩子函数约束其行为。

public abstract class AbstractDoctor {

    protected boolean checkIsCure =true;

    //了解病情
    protected abstract void knowAboutSymptoms();
    //分析病情
    protected abstract void analysisIllness();
    //治疗患者
    protected abstract void curePatient();

    //检查病人是否需要治疗,默认需要
    //钩子函数
    protected boolean checkIsCure(){
        return true;
    }

    public void work() {
        knowAboutSymptoms();
        analysisIllness();
        if (checkIsCure()){
            curePatient();
        }
    }

}
public class ChineseDoctor extends AbstractDoctor {

    @Override
    public void knowAboutSymptoms() {
        System.out.println("中医通过望闻问切了解病人病情");
    }
    @Override
    public void analysisIllness() {
        System.out.println("得知病情后,通过自己丰富的经验分析病情,制定治疗方案");
    }
    @Override
    public void curePatient() {
        System.out.println("根据治疗方案给你抓中药");
    }
    @Override
    protected boolean checkIsCure(){
        return super.checkIsCure;
    }

    protected void setCheckIsCure(boolean isCure){
        super.checkIsCure=isCure;
    }
}
public class Client {


    public static void main(String[] args) {
        ChineseDoctor chineseDoctotr = new ChineseDoctor();
        chineseDoctotr.setCheckIsCure(false);
        chineseDoctotr.work();

        System.out.println("===============华丽的分隔符========================");

        AbstractDoctor westDoctor = new WestDoctor();
        westDoctor.work();

    }
}

测试结果:
中医通过望闻问切了解病人病情
得知病情后,通过自己丰富的经验分析病情,制定治疗方案
===============华丽的分隔符========================
简单询问,就让你去拍个片
根据x光片,分析病人病情,制定治疗方案
打针,输液,药片各来一打,包治百病

通过钩子函数给中医赋予了若病人治疗无聊,则可以选择不治疗。其实钩子函数就是子类方法决定模板方法的执行结果,这样就灵活了许多。

总结

模板方法模式就是在模板方法中按照一定的规则和顺序调用基本方法,具体到前面的例子就是先调用knowAboutSymptoms(),再调用analysisIllness(),然后调用checkIsCure()选择是否执行curePatient()。
按照我们的设计习惯抽象类负责定义,实现类负责实现具体逻辑,而模板方法确实抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响到了父类的结果,所以其最大的缺点就是增大了阅读代码的难度。其最大的优点就是封装了不变部分,扩展了可变部分,提取公共代码,利于维护。


Alpaca
142 声望33 粉丝