设计模式之——模板方法

前言:

模板方法(Template Method)属于设计模式中的行为模式,它的特点是:定义一个操作中的算法的 框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可 重定义该算法的某些特定步骤。

优点:

  1. 封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
  2. 父类中提取了公共的部分代码,便于代码复用。
  3. 部分方法(通常是指不共用的方法)是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

缺点:

  1. 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
  2. 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

场景与实现:

初中校园作息时间和高中校园作息时间都差不多,举例几个共同点:上早自习,课间操,午休,下午课,放学。只是时间上可能存在一些区别。因此可以将这些行为抽象并抽取相同的行为定义为一个模板。然后继承这套模板,分别实现各自的作息时间。

分析实现:

1.定义一个抽象类:AbstractSchoolLifeTemplate 将共同的行为定义成抽象方法,等待子类实现

2.创建初中生活作息类MiddleSchoolLife、高中生活作息类 SeniorSchoolLife,都分别继承AbstractSchoolLifeTemplate 并实现抽象方法。

3.创建测试类测试

代码实现:

项目结构图:

主要就是一个作息时间抽象类,两个具体实现类,一个测试类

相关类源码:

作息时间抽象类AbstractSchoolLifeTemplate 

这个类定义了几个抽象方法,等待子类实现,还写了一个公共方法(请看上面优点2:父类中提取了公共的部分代码,也就是不变代码,便于代码复用)来调用各个抽象方法,用来实现一天的作息时间表的输出

package com.dp.template;

/**
 * 校园生活作息抽象类
 */
public abstract class AbstractSchoolLifeTemplate {
    public String studentType;
    //早读课
    public abstract void moring();
    //课间操
    public abstract void morningExercises();
    //午休
    public abstract void siesta();
    //下午课
    public abstract void afternoonClasses();
    //放学
    public abstract void afterSchool();

    //学校的一天
    public void SchoolLifeOfDay(){
        System.out.println(studentType+"学校作息时间安排:");
        this.moring();
        this.morningExercises();
        this.siesta();
        this.afternoonClasses();
        this.afterSchool();
    }
}
初中作息实现类MiddleSchoolLife

这个类继承了抽象类AbstractSchoolLifeTemplate ,必须实现AbstractSchoolLifeTemplate 定义的抽象方法

package com.dp.template;

/**
 * 初中作息实现类
 */
public class MiddleSchoolLife extends AbstractSchoolLifeTemplate{
    public MiddleSchoolLife(String studentType){
        this.studentType = studentType;
    }
    @Override
    public void moring() {
        System.out.println("8:00 上早自习!");
    }

    @Override
    public void morningExercises() {
        System.out.println("9:30 课间操");
    }

    @Override
    public void siesta() {
        System.out.println("12:00-14:00 午休");
    }

    @Override
    public void afternoonClasses() {
        System.out.println("14:00 上课");
    }

    @Override
    public void afterSchool() {
        System.out.println("16:30 放学");
    }
}
高中作息实现类:SeniorSchoolLife

这个类和初中作息时间类一样的目的,实现高中作息具体时间

package com.dp.template;

/**
 * 高中作息实现类
 */
public class SeniorSchoolLife extends AbstractSchoolLifeTemplate{
    public SeniorSchoolLife(String studentType){
        this.studentType = studentType;
    }
    @Override
    public void moring() {
        System.out.println("7.30 上早自习!");
    }

    @Override
    public void morningExercises() {
        System.out.println("10:00 课间操");
    }

    @Override
    public void siesta() {
        System.out.println("12:00-14:30 午休");
    }

    @Override
    public void afternoonClasses() {
        System.out.println("14:30 上课");
    }

    @Override
    public void afterSchool() {
        System.out.println("17:10 放学");
    }
}

测试类:TestMain

package com.dp.template;

public class TestMain {
    public static void main(String[] args) {
        //创建初中作息类
        AbstractSchoolLifeTemplate middleSchoolLife = new MiddleSchoolLife("初中生");
        //创建高中作息类
        AbstractSchoolLifeTemplate seniorSchoolLife = new SeniorSchoolLife("高中生");
        //调用父类的作息安排方法(共同)
        middleSchoolLife.SchoolLifeOfDay();
        System.out.println("========================");
        //调用父类的作息安排方法(共同)
        seniorSchoolLife.SchoolLifeOfDay();
    }
}

测试结果:

总结:

模板方法是一个比较实用的模式,有看过 Dubbo源码的朋友应该知道,里面大量代码运用了模板方法设计模式,为什么 Dubbo 可以支持很多种注册中心?其实本质就是用了模板方法设计模式,使得可以扩展多种注册中心。掌握好模板方法,对读源码有非常大的帮助。不懂设计模式去阅读源码的时候,可能会感觉那些代码那么绕?调来调去的。 当你了解了常用的设计模式之后,看源代码就可以直截了当的知道是用什么设计模式,为什么用这个设计模式?目的是什么?有了这层思考, 就像有一条线将以前散落在各地的知识点连接起来,成了可以推敲的知识。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值