设计模式(四)模板方法模式

172 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

我们小时候肯定都经历过在课堂上抄题目,将老师出的题目抄下来然后去做,这样就免不了有个别粗心的同学将题目抄错,尤其是数学题,将数字抄错,这样做出来的答案基本就是错的,但现在就很少有抄题目的时候了,老师都会将题目写好,然后复印,发给学生做,这样就保证了每个学生上面的题目是完全一致的,而这其实就体现了模板方法模式。

模板方法模式,就是定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类不可以不可以改变一个算法的结构即可重定义该算法的某些特定步骤。下面给出模板方法模式的类图结构和实例代码帮助大家理解。

图片

public abstract class AbstractClass {
    public abstract void primitiveOperation1();
    public abstract void primitiveOperation2();
    public void templateMethod(){
        primitiveOperation1();
        primitiveOperation2();
        System.out.println("finish");
    }
}

public class ConcreteClass extends AbstractClass {
    @Override
    public void primitiveOperation1() {
        System.out.println("to do one");
    }

    @Override
    public void primitiveOperation2() {
        System.out.println("to do two");
    }
}

public class TemplateTest {
    public static void main(String[] args) {
        AbstractClass abstractClass= new ConcreteClass();
        abstractClass.templateMethod();
    }
}

  • AbstractClass是抽象类,定义并实现了一个模板方法,这个模板方法一般是一个具体方法,它给出了一个顶级逻辑骨架,而其中的逻辑组成步骤在相应抽象操作中,推迟到子类去实现它。

  • ConcreteClass:实现父类所定义的一个或多个抽象方法,每一个AbstractClass都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法不同的实现。

现在有一个场景,我们去大学报到,基本上每个学校流程都是凭录取通知书到各院系报到,然后缴费,领取生活用品,然后去宿舍,但每个学校可能具体的流程还不一样,可能A学校在缴费的时候需要拍照片,办理校园卡,B学校在缴费的时候需要关注学校公众号,线上办理业务。现在我们就用具体代码实现这个场景。

图片

public abstract class RegisterSchool {
    public void register(){
        checkIn();//报到
        bill();//缴费
        getSupplies();//领取生活用品
        toDormitory();//去宿舍

    }

    protected abstract void toDormitory();

    protected abstract void getSupplies();

    protected abstract void bill();

    protected abstract void checkIn();
}

public class AschoolRegister extends RegisterSchool {
    @Override
    protected void toDormitory() {
        System.out.println("去宿舍报到");
    }

    @Override
    protected void getSupplies() {
        System.out.println("领取锅碗瓢盆");
    }

    @Override
    protected void bill() {
        System.out.println("缴学费,拍照,办理校园卡");
    }

    @Override
    protected void checkIn() {
        System.out.println("去院系报到");
    }
}

public class BschoolRegister extends RegisterSchool {
    @Override
    protected void toDormitory() {
        System.out.println("去宿舍报到");
    }

    @Override
    protected void getSupplies() {
        System.out.println("领取锅碗瓢盆");
    }

    @Override
    protected void bill() {
        System.out.println("缴学费,关注学院微信公众号");
    }

    @Override
    protected void checkIn() {
        System.out.println("去院系报到");
    }
}

public class SchoolTest {
    public static void main(String[] args) {
        RegisterSchool registerSchoolA=new AschoolRegister();
        RegisterSchool registerSchoolB=new BschoolRegister();
        registerSchoolA.register();
        registerSchoolB.register();
    }
}

RegisterSchool中的register方法就相当于模板方法,对外提供调用,B学校和A学校用自己的具体类继承RegisterSchool完成具体逻辑处理,这样以后再有其他学校也只需继承RegisterSchool类即可,这样就剩去了很多冗余代码。

模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,去除了子类中公共的代码,它鼓励我们恰当使用继承来实现代码复用。这样的设计方式也有其弊端,子类的执行结果会影响父类的结果,造成代码阅读的难度。

模板方法模式适用于多个子类中有共有的代码,并且逻辑基本相同;对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。