23种设计模式之模板方法模式

模板方法模式是一种行为设计模式,通过定义算法的框架并在抽象类中实现不变部分,将可变部分留给子类实现。这种模式在代码复用和控制扩展方面具有优势,适用于步骤固定但部分细节可变的场景。例如,将对象放入容器的流程,模板方法模式可以定义打开和关闭容器的通用步骤,而放置对象的具体操作由不同子类实现。在实际开发中,如Java框架中广泛应用此模式,允许开发者通过继承和重写特定方法来扩展功能。
摘要由CSDN通过智能技术生成

23种设计模式之模板方法模式

参考资料

下文如有错漏之处,敬请指正

一、简介

定义

定义一个算法的框架,封装步骤相同的部分,将特定(不同)步骤的部分交由子类完成,以此达到代码复用。

特点

  • 模板模式是一种行为型模式
  • 模板方法模式就是抽象类与具体子类之间的协作(继承机制)

优点

  • 封装了不变部分,扩展可变部分

    把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。

  • 提取了公共的部分代码,便于代码复用。

  • 行为由父类控制,子类实现

    基本方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

缺点

  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

通用类图

在这里插入图片描述

  • AbstractClass

    抽象模板

    定义一个算法的骨架它由一个模板方法和若干个基本方法构成。

    • 模板方法

      模板方法定义了算法的骨架,按某种顺序调用基本方法。

    • 基本方法

      基本方法也叫做基本操作(特定步骤),是由子类实现的方法,并且在模板方法被调用。

      基本方法包含以下几种类型:

      • 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
      • 抽象方法:在抽象类中定义,由具体子类实现特定步骤的内容。
      • 钩子方法:在抽象类中定义,由具体子类实现用于控制父类的行为。
  • ConcreteClass

    具体模板

    实现抽象模板类中所定义的一个或多个抽象方法。

应用场景

  • 多个子类有公有的方法,并且逻辑基本相同时,可以使用模板方法模式,抽取公有方法为模板方法。
  • 算法的整体步骤固定,但其中个别部分易变时,可以使用模板方法模式,将容易变的部分抽象出来,由子类实现。

二、模板方法模式

需求:

把某个XX装入YY容器分为四个步骤,第一个步骤是准备YY容器,父类默认使用冰箱作为容器,第二个步骤“打开冰箱”和最后一个步骤“关闭冰箱”步骤内容相同,第三个步骤是将XX装入YY,因为XX不同,因此子类需要重写第三个步骤。

AbstractClass:抽象模板类,定义算法的骨架。

ConcreteClass:具体模板类,实现抽象类的所有抽象方法。ConcreteBowl(放碗)、ConcreteElephant(放大象),ConcreteAir(放空气)

AbstractClass:

package templateMethod;

public abstract class AbstractClass {
    private String container="冰箱";

    protected void setContainer(String container) {
        this.container = container;
    }

    public void TemplateMethod() //模板方法
    {

        // 如果子类不使用容器的话,则直接进入最后一个步骤
        if (HookMethod()) {
            SpecificMethod1();
            abstractMethod();
            SpecificMethod2();
        }else {
            abstractMethod();
        }
    }


    //钩子方法,限制父类的行为。父类默认使用冰箱,当子类修改为false,则不使用容器。
    protected boolean HookMethod() {
        return true;
    }


    // 具体方法
    protected void SpecificMethod1() {
        System.out.println("打开"+container);
    }
    protected void SpecificMethod2() {
        System.out.println("关闭"+container);
    }

  	// 抽象方法
    protected abstract void abstractMethod();


    protected String getContainer() {
        return container;
    }
}

ConcreteElephant:

package templateMethod;

public class ConcreteElephant extends AbstractClass {

    @Override
    protected void abstractMethod() {
        System.out.println("将大象装入"+this.getContainer());
    }
}

ConcreteBowl:

package templateMethod;

public class ConcreteBowl extends AbstractClass {
    public ConcreteBowl() {
        this.setContainer("橱柜");
    }

    @Override
    protected void abstractMethod() {
        System.out.println("将碗装入"+this.getContainer());
    }
}

ConcreteAir:

package templateMethod;

public class ConcreteAir extends AbstractClass {
    public ConcreteAir() {
        this.setContainer("空气");
    }

    // 不使用容器
    @Override
    protected boolean HookMethod() {
        return false;
    }

    @Override
    protected void abstractMethod() {
        System.out.println("将空气装入"+this.getContainer());
    }
}

Client:

package templateMethod;

public class Client {
    public static void main(String[] args) {
        AbstractClass elephant = new ConcreteElephant();
        elephant.TemplateMethod();
        System.out.println("========================");

        AbstractClass bowl = new ConcreteBowl();
        bowl.TemplateMethod();
        System.out.println("========================");
        
        AbstractClass air = new ConcreteAir();
        air.TemplateMethod();

        /**
         * 输出结果:
         *        打开冰箱
         *        将大象装入冰箱
         *        关闭冰箱
         *        ========================
         *        打开橱柜
         *        将碗装入橱柜
         *        关闭橱柜
         *        ========================
         *        将空气装入空气
         */
    }
}

三、总结

模板方法模式在一些开源框架中应用非常多,它提供了一个抽象类,然后开源框架写了一堆子类。在《××× In Action》中就说明了,如果你需要扩展功能,可以继承这个抽象类,覆写protected方法,然后调用一个类似execute方法,就可以完成你的扩展开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值