设计模式之模板方法模式

1.简要概述

  • 模板方法模式也叫作模板模式,属于行为型设计模式。
  • 模板方法模式定义了一个操作中的算法骨架,并将一些特殊的步骤延迟到子类中实现。
  • 模板方法模式的核心思想,就是在父类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤,以完成不同的需求。
  • 模板方法模式中,也可以定义钩子方法,钩子方法可以对其他方法进行约束,通常返回一个boolean类型的标识,用来判断是否执行某一个基本方法,钩子方法的引入使得子类可以控制父类的行为。

2.模式结构

👉通常由一个模板抽象类( 负责定义某个算法的骨架,也就是整个过程步骤,然后实现那些通用的、不需要改变的步骤逻辑 ),多个具体的实现类( 负责实现算法骨架中那些比较特殊的步骤逻辑 ),一个客户类( 负责对模板类进行调用,完成算法的整个过程)共同组成。

请添加图片描述

3.实现代码

举例 💡 :假设我们现在要做不同口味的豆浆,首先我们知道做豆浆的基本步骤就是:打开豆浆机、放入原料、启动豆浆机、关闭豆浆机。然后对于制作不同口味的豆浆,只是放入的原料不同而已,所以我们就可以使用模板方法模式处理该问题,将放入原料的过程单独提取出来。

豆浆抽象类(模板抽象类)

public abstract class SoyaMilk {

    // 制作豆浆
    public final void make() {
        open();
        add();
        start();
        close();
    }
	
    // 打开豆浆机
    public void open() {
        System.out.println("打开豆浆机");
    }
    
    // 放入原料
    public abstract void add();
    
	// 启动豆浆机
    public void start() {
        System.out.println("启动豆浆机");
    }
    
    // 关闭豆浆机
    public void close() {
        System.out.println("关闭豆浆机");
    }
}

红豆豆浆(具体实现类)

public class RedBeanSoyaMilk extends SoyaMilk {
    @Override
    public void add(){
        System.out.println("加入红豆");
    }
}

小米豆浆(具体实现类)

public class MilletSoyaMilk extends SoyaMilk {
    @Override
    public void add(){
        System.out.println("加入小米");
    }
}

芝麻豆浆(具体实现类)

public class SesameSoyaMilk extends SoyaMilk {
    @Override
    public void add(){
        System.out.println("加入芝麻");
    }
}

客户类

// 测试客户端
public class SoyaMilkClient{
    public static void main(String[] args) {
        // 制作红豆豆浆
        SoyaMilk soyaMilk1 = new RedBeanSoyaMilk();
        soyaMilk1.make();
        
        // 制作小米豆浆
        SoyaMilk soyaMilk2 = new MilletSoyaMilk();
        soyaMilk2.make();
        
        // 制作芝麻豆浆
        SoyaMilk soyaMilk3 = new SesameSoyaMilk();
        soyaMilk3.make();
    }
}

4.优点好处

  • 模板方法模式中,实现了代码最大化复用,子类直接继承并使用父类中已实现的方法。
  • 模板方法模式中,行为由⽗类管理,子类进行可变部分的扩展,这样非常有利于系统的开发拓展和迭代。
  • 模板方法模式中,通过父类调用其子类的操作,让子类进行扩展实现新的行为,符合开闭原则。
  • 模板方法模式中,仅允许子类重写一个算法中的特定部分,使得算法其他部分修改对其所造成的影响大大减小。

5.缺点弊端

  • 模板方法模式中,每一个不同的实现都需要编写一个子类去实现,这样如果一个系统中存在很多的不同实现,那么就会产生许多子类,使得整个系统变得庞大。
  • 模板方法模式中,通过子类抑制默认步骤实现可能会导致违反里氏替换原则。

6.应用场景

  • 当我们需要完成某个相似的过程,且这些过程的一系列步骤基本相同,只有个别步骤在实现中略有差异的时候,我们就可以使用模板方法。
  • 当系统中需要进行分层来控制某个过程的不同实现,即由上层控制流程,下层负责具体细则实现的时候,我们就可以使用模板方法。

7.应用示例

Spring源码中的应用程序上下文环境进行刷新时的过程

  1. 这里的AbstractApplicationContext抽象类就可以看作是模板方法中的抽象模板类,该类中定义了一个用于刷新的方法,我们可以看到在方法中执行了一系列的方法调用,那么这个调用的过程就可以看做是模板方法中的执行步骤。

    请添加图片描述

    请添加图片描述

  2. 其中,我们可以找出里面的某些方法是抽象的,也就是待子类去实现的,那么这些方法就可以看作是模板方法中特定的那些算法步骤。

    请添加图片描述

  3. 下面,我们找到AbstractApplicationContext抽象类的一个具体实现,可以看到该类对上面的refreshBeanFactory方法进行了具体的实现。

    请添加图片描述

    请添加图片描述

  4. 上面所涉及相关类的关联关系如下图所示:

    请添加图片描述

  5. 我们通过类图结构可以看出,AbstractApplicationContext类中定义了执行某项操作的通用步骤,而其中的某些步骤方法需要通过子类去实现,所以这个过程使用了模板方法模式进行设计。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小吉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值