模板方法模式

模板方法模式定义了算法的框架,允许子类在不改变结构的情况下重写特定步骤。这种模式用于在父类中定义处理流程,子类实现具体处理,以实现算法的通用性和定制化。文章通过代码示例展示了如何使用模板方法模式,包括抽象类和具体子类的实现,并讨论了模式的优缺点及适用场景。
摘要由CSDN通过智能技术生成

模板方法 Template Method

模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。

🔖 通常是对算法的特定步骤进行优化,而不是对整个算法进行修改。


为什么要使用?

模板方法模式的对象职责:

在父类中定义处理流程的框架,在子类中实现具体处理。

👉 期望在一个通用的算法或流程框架下进行自定义开发。

👉 避免同样的代码逻辑进行重复编码。

💡 模板方法模式将通用操作和流程处理交给父类处理,其他具体操作交由子类实现。


模式结构

  • 抽象类(Abstract Class)会声明作为算法步骤的方法,以及依次调用它们的实际模板方法。算法步骤可以被声明为 abstract 类型,也可以提供一些默认实现。
  • 具体类(Concrete ­Class)可以重写所有步骤,但不能重写模板方法自身。

模板方法模式的类图:

在这里插入图片描述


模式实现

该示例使用模板方法模式将 display 操作交由父类实现,其他操作由子类(显示单个字符的类 CharDisplay 和显示整个字符串的类 StringDisplay )实现,display 主要负责控制 openprintclose 的调用顺序。

示例程序的类图

在这里插入图片描述

代码实现
抽象类
package example;

/** 抽象模板类 */
public abstract class AbstractDisplay {
    /** 子类需要实现的方法 */
    public abstract void open();

    /** 子类需要实现的方法 */
    public abstract void print();

    /** 子类需要实现的方法 */
    public abstract void close();

    /** 模板方法,处理流程 */
    public final void display() {
        open();
        print();
        close();
    }
}
具体类
package example;

/** 具体子类,字符方式打印 */
public class CharDisplay extends AbstractDisplay {
    private char ch;

    public CharDisplay(char ch) {
        this.ch = ch;
    }

    /** 子类需要实现的方法 */
    @Override
    public void open() {
        System.out.print("<<");
    }

    /** 子类需要实现的方法 */
    @Override
    public void print() {
        System.out.print(ch);
    }

    /** 子类需要实现的方法 */
    @Override
    public void close() {
        System.out.println(">>");
    }
}
package example;

/** 具体子类,字符串方式打印 */
public class StringDisplay extends AbstractDisplay {
    private String str;

    public StringDisplay(String str) {
        this.str = str;
    }

    /** 子类需要实现的方法 */
    @Override
    public void open() {
        System.out.print("+");
        for (int i = 0; i < str.length(); i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }

    /** 子类需要实现的方法 */
    @Override
    public void print() {
        printLine();
        System.out.print("|");
        for (int i = 0; i < str.length(); i++) {
            System.out.print(str.charAt(i));
        }
        System.out.println("|");
        printLine();
    }

    /** 子类需要实现的方法 */
    @Override
    public void close() {
        System.out.print("+");
        for (int i = 0; i < str.length(); i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }

    /** 子类特有的私有方法 */
    private void printLine() {
        System.out.print("|");
        for (int i = 0; i < str.length(); i++) {
            System.out.print("-");
        }
        System.out.println("|");
    }
}
代码测试
import example.AbstractDisplay;
import example.CharDisplay;
import example.StringDisplay;

/** 测试模板方法模式 */
public class Test {
    public static void main(String[] args) {
        AbstractDisplay charDisplay = new CharDisplay('H');
        AbstractDisplay stringDisplay = new StringDisplay("Hellovie");
        System.out.println("CharDisplay实现");
        charDisplay.display();
        
        System.out.println("\n----------------- 分割线 -----------------\n");
        
        System.out.println("StringDisplay实现");
        stringDisplay.display();
    }
}
输出结果
CharDisplay实现:
<<H>>

----------------- 分割线 -----------------

StringDisplay实现:
+--------+
|--------|
|Hellovie|
|--------|
+--------+

常用场景和解决方案

  • 多个类有相同的方法并且逻辑可以共用时。
  • 将通用的算法或固定流程设计为模板,在每一个具体的子类中再继续优化算法步骤或流程步骤时。
  • 重构超长代码时,发现某一个经常使用的共有方法。
  • 当你只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时。

模式的优缺点

优点缺点
你可仅允许客户端重写一个大型算法中的特定部分,使得算法其他部分修改对其所造成的影响减小。部分客户端可能会受到算法框架的限制。
你可将重复代码提取到一个超类中,有效去除重复代码。通过子类抑制默认步骤实现可能会导致违反里氏替换原则
有助于找到更通用的模板。模板方法中的步骤越多,其维护工作就可能会越困难。

拓展知识

  • 工厂方法模式是模板方法模式的一种特殊形式。同时,工厂方法可以作为一个大型模板方法中的一个步骤。
  • 继承的结构容易带来“修改一个类而影响所有类”的情况。


🔙 设计模式

📌最后:希望本文能够给您提供帮助,文章中有不懂或不正确的地方,请在下方评论区💬留言!

🔗参考文献:

🌐 设计模式 --refactoringguru

▶️ bilibili-趣学设计模式;黄靖锋. --拉勾教育

📖 图解设计模式 /(日)结城浩著;杨文轩译. --北京:人民邮电出版社,2017.1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值