文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一文搞懂设计模式—模板方法模式

2024-11-30 01:58

关注

在软件开发中,我们经常会遇到需要定义一组相似操作的场景。这些操作可能在整体上有着相同的结构,但在细节上有所差异。如果每次都重复编写这些操作的通用结构,会导致代码的冗余性,同时也增加了后期维护的难度。为了解决这个问题,模板方法模式应运而生。

使用场景

模板方法模式适用于以下场景:

JUC 下的 AQS 就使用到了模板方法模式,其中 acquire() 是模板方法。tryAcquire() 方法的具体实现去交给子类完成。


    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

实现方式

结构说明

模板方法模式由抽象类和具体子类组成。抽象类定义了算法的框架,其中包含了一个或多个抽象方法,用于由具体子类实现。具体子类继承抽象类,并根据需要重写其中的抽象方法,从而实现具体的细节。

在模板方法模式中,通常涉及以下几个角色:

示例代码

以下是一个简单的代码示例:

// 抽象类,定义模板方法和抽象步骤方法
public abstract class AbstractClass {
    // 模板方法,定义算法的整体结构
    public final void templateMethod() {
        step1();
        step2();
        step3();
    }
     // 模板公共方法
    protected final void step1(){
      System.out.println("ConcreteClass: Step 1");
    }
    // 抽象步骤方法,由子类实现具体的步骤逻辑
    protected abstract void step2();
    // 抽象步骤方法,由子类实现具体的步骤逻辑
    protected abstract void step3();
}

// 具体子类,实现抽象步骤方法
public class ConcreteClass extends AbstractClass {
    
    protected void step2() {
        System.out.println("ConcreteClass: Step 2");
    }

    protected void step3() {
        System.out.println("ConcreteClass: Step 3");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AbstractClass abstractClass = new ConcreteClass();
        abstractClass.templateMethod();
    }
}

在上述代码中,我们首先定义了一个抽象类 AbstractClass,其中包含了模板方法和抽象方法。然后,我们创建了具体子类 ConcreteClass,根据需要实现了抽象方法。

在客户端代码 Client 中,我们创建了具体子类的对象,并调用了模板方法 templateMethod(),从而执行了定义好的算法。

运行该代码将输出以下结果:

ConcreteClass: Step 1
ConcreteClass: Step 2
ConcreteClass: Step 3

注意:

钩子方法

钩子方法(Hook Method)是模板方法模式中的一种特殊方法,用于在抽象类中提供一个默认的实现,但允许具体子类选择性地进行重写或扩展。钩子方法允许子类在不改变算法骨架的情况下,对算法的某些步骤进行定制。

以下是一个包含钩子方法的 Java 示例代码:

// 抽象类,定义模板方法和钩子方法
public abstract class AbstractClass {
    // 模板方法,定义算法的整体结构
    public final void templateMethod() {
        step1();
        step2();
    // 钩子方法的调用
        if (hookMethod()) {  
            step3();
        }
    }

    protected abstract void step1();

    protected abstract void step2();

    // 钩子方法,默认返回true,子类可以选择性地重写
    protected boolean hookMethod() {
        return true;
    }

    protected abstract void step3();
}

// 具体子类1
public class ConcreteClass1 extends AbstractClass {
    protected void step1() {
        System.out.println("ConcreteClass1: Step 1");
    }

    protected void step2() {
        System.out.println("ConcreteClass1: Step 2");
    }

    protected void step3() {
        System.out.println("ConcreteClass1: Step 3");
    }
}

// 具体子类2
public class ConcreteClass2 extends AbstractClass {
    protected void step1() {
        System.out.println("ConcreteClass2: Step 1");
    }

    protected void step2() {
        System.out.println("ConcreteClass2: Step 2");
    }

    protected boolean hookMethod() {
        return false; // 重写钩子方法,返回false
    }

    protected void step3() {
        System.out.println("ConcreteClass2: Step 3");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AbstractClass class1 = new ConcreteClass1();
        class1.templateMethod();

        System.out.println("------------------");

        AbstractClass class2 = new ConcreteClass2();
        class2.templateMethod();
    }
}

在上述代码中,我们定义了一个抽象类 AbstractClass,其中包含模板方法 templateMethod() 和钩子方法 hookMethod()。在模板方法中,我们先执行了step1() 和 step2() 两个基本操作方法,然后通过调用钩子方法决定是否执行 step3()。

具体子类 ConcreteClass1 和 ConcreteClass2 继承了抽象类,并实现了基本操作方法 step1()、step2() 和钩子方法 hookMethod()、step3()。

在客户端代码 Client 中,我们分别创建了具体子类的对象,并调用其模板方法,从而执行了定义好的算法。

运行该示例代码将输出以下结果:

ConcreteClass1: Step 1
ConcreteClass1: Step 2
ConcreteClass1: Step 3
------------------
ConcreteClass2: Step 1
ConcreteClass2: Step 2

通过重写钩子方法,具体子类可以选择性地对算法进行定制化。这就展示了钩子方法在模板方法模式中的应用。

优缺点

优点

缺点

总结

模板方法是一种简单但非常实用的设计模式,它通过定义一个算法的框架,并将具体实现延迟到子类中,实现了代码复用和扩展的目的。在具体实现步骤相对固定、但又存在差异性的情况下,模板方法模式能够很好地解决代码重复和维护难度的问题。

来源:Java随想录内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯