简介

  • 是一种行为型设计模式

  • 模板方法(Template Method)模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

主要组成部分:

  • 抽象模板类(Abstract Template Class):定义了算法的骨架,其中包含了一个或多个抽象方法来表示算法的特定步骤。这个类中的模板方法定义了算法的执行顺序。

  • 具体子类(Concrete Subclasses):继承自抽象模板类,并实现了其中的抽象方法,以提供算法步骤的具体实现。

工作流程

  • 抽象模板类中包含了一个或多个抽象方法,这些方法用于表示算法中的不同步骤。

  • 抽象模板类中定义了一个模板方法,该方法描述了算法的执行顺序,并在其中调用了抽象方法。

  • 具体子类继承抽象模板类,并实现其中的抽象方法,以提供算法的具体实现。

  • 客户端通过创建具体子类的实例来使用算法,然后调用模板方法执行算法。

事例

结构

代码

抽象模板类

/**
 * @author: lpy
 * @Date: 2023/10/20
 */
public abstract class TestPaper {
    private String name;
    private String grade;

    public TestPaper(String name, String grade){
        this.name = name;
        this.grade = grade;
    }

    public void getInf(){
        System.out.println("学生:"+this.name+"\n"+"年级"+this.grade);
    }

    public void testQuestion1(){
        System.out.println("第一道题:"+answer1());
    }
    protected abstract String answer1();

    public void testQuestion2(){
        System.out.println("第二道题:"+answer2());
    }
    protected abstract String answer2();

    public void testQuestion3(){
        System.out.println("第三道题:"+answer3());
    }
    protected abstract String answer3();

    public void testQuestion4(){
        System.out.println("第四道题:"+answer4());
    }
    protected abstract String answer4();
}

具体子类

/**
 * @author: lpy
 * @Date: 2023/10/20
 */
public class TestPaperA extends TestPaper{

    public TestPaperA(String name, String grade) {
        super(name, grade);
    }

    @Override
    public String answer1() {
        return "A";
    }

    @Override
    public String answer2() {
        return "B";
    }

    @Override
    public String answer3() {
        return "C";
    }

    @Override
    public String answer4() {
        return "D";
    }
}
/**
 * @author: lpy
 * @Date: 2023/10/20
 */
public class TestPaperB extends TestPaper{

    public TestPaperB(String name, String grade) {
        super(name, grade);
    }

    @Override
    public String answer1() {
        return "BC";
    }

    @Override
    public String answer2() {
        return "B";
    }

    @Override
    public String answer3() {
        return "C";
    }

    @Override
    public String answer4() {
        return "D";
    }
}

测试类

public class TemplateFunctionTest {
    public static void main(String[] args) {
        // 将子类变量的声明改成父类,利用了多态性,实现了代码的复用
        TestPaper testPaperA = new TestPaperA("学生A","大二");
        testPaperA.getInf();
        testPaperA.testQuestion1();
        testPaperA.testQuestion2();
        testPaperA.testQuestion3();
        testPaperA.testQuestion4();

        System.out.println("\n");
        TestPaper testPaperB = new TestPaperB("学生B","大三");
        testPaperB.getInf();
        testPaperB.testQuestion1();
        testPaperB.testQuestion2();
        testPaperB.testQuestion3();
        testPaperB.testQuestion4();
    }
}

应用

参考文章:《设计模式|模板方法模式应用》. BaseExecutor 的子类有四个分别是 SimpleExecotor、ReuseExecutor、BatchExecutor、ClosedExecutor,由于这里使用了模板方法模式,一级缓存等固定不变的操作都封装到了 BaseExecutor 中,因此子类就不必再关心一级缓存等操作,只需要专注实现doUpdate() 方法、doQuery() 方法、doQueryCursor() 方法、doFlushStatement()4个基本方法的实现即可。

模板方法模式优缺点

  • 优点:
    • 代码重用:模板方法模式促进了代码重用,因为通用的算法骨架在抽象模板类中只定义一次,而具体步骤的实现可以由多个子类提供。

    • 标准化算法结构:模板方法模式允许将算法的骨架定义在一个地方,以确保算法的一致性和标准化,这有助于提高代码的可维护性。

    • 降低维护成本:当需要修改算法的某个步骤时,只需在抽象模板类中进行修改,而不需要修改所有具体子类的相同步骤。

    • 灵活性:模板方法模式为子类提供了灵活性,允许子类在不改变算法整体结构的情况下重新定义特定步骤的实现。

    • 逻辑封装:模板方法模式将共享的逻辑封装在抽象模板类中,使代码更具可读性和可维护性。

  • 缺点:

    • 过多的抽象层级:如果不谨慎设计,使用模板方法模式可能会导致过多的抽象层级,使代码复杂化。

    • 破坏封装:模板方法模式可能会破坏封装,因为具体子类需要实现抽象方法,而这些方法可能需要访问抽象模板类中的内部状态。

    • 复杂性增加:在某些情况下,模板方法模式可能使代码变得更加复杂,因为需要定义抽象模板类和多个具体子类,这可能不适用于简单的算法。

    • 不适用于所有情况:模板方法模式不适用于所有场景,特别是当算法的步骤变化不大或无需复用时,引入模板方法模式可能显得冗余。

7 大设计原则

不能全部遵守 , 也不能不遵守 , 注意平衡 功能 和 系统复杂度 , 找到最合适的一个点 ;

- 单一职责原则(Single Responsibility Principle - SRP):
这个原则规定一个类应该只有一个改变的理由,也就是说,一个类应该只有一个单一的职责。这有助于保持类的简单性和可维护性,因为每个类只需关注一个特定的功能。

- 开放-封闭原则(Open-Closed Principle - OCP):
开放-封闭原则要求系统中的软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改原有代码。

- 里氏替换原则(Liskov Substitution Principle - LSP):
里氏替换原则规定,子类应该能够替换其父类,而不会影响程序的正确性。也就是说,子类应该继承父类的行为,但可以扩展或修改该行为,但不应该改变父类的行为。

- 接口隔离原则(Interface Segregation Principle - ISP):
接口隔离原则要求一个类不应该强迫其客户端依赖于它们不需要的接口。应该根据客户端的需求定义小而精确的接口,而不是大而笨重的接口。

- 依赖倒置原则(Dependency Inversion Principle - DIP):
依赖倒置原则要求高级模块不应该依赖于低级模块,它们都应该依赖于抽象。具体来说,这意味着应该通过抽象接口或抽象类来定义模块之间的依赖关系,而不是直接依赖于具体实现。

- 迪米特法则(Law of Demeter - LoD):
迪米特法则也被称为最少知识原则,它要求一个对象应该只与其密切的朋友交互,而不应该暴露太多的信息给外部对象。这有助于减少对象之间的耦合度,提高系统的灵活性。

- 合成复用原则(Composite Reuse Principle - CRP):
合成复用原则鼓励通过组合(合成)已有的类来实现新功能,而不是通过继承现有的类。这样可以降低系统的耦合度,并且更加灵活。

源码位置

全部源码github.com/xs-alpha/designPattern

如有内容侵权,麻烦联系博主删除

参考文献

浙公网安备33011302000604

辽ICP备20003309号