掌握设计模式--模板方法模式

模板方法模式(Template Method Pattern)

模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个操作中的算法骨架,并允许子类在不改变算法结构的情况下重新定义算法的某些步骤。

核心思想:模板方法定义算法骨架,浅白地说,定义通用的逻辑框架、控制流程和调用顺序,而具体的实现将延迟到子类,从而在不改变结构的前提下扩展算法的灵活性。再简单点说:定义了一个处理逻辑的步骤(一个骨架),具体的处理逻辑由子类继承后实现(真正的血肉)。

主要组成部分

  1. 抽象类(AbstractClass)
  • 定义模板方法,模板方法包含算法的骨架。
  • 实现一些不变的步骤,或声明需要子类实现的抽象方法。
  1. 具体类(ConcreteClass)
  • 实现抽象类中声明的抽象方法,从而完成算法的具体步骤。

案例实现

实现一个简单的自定义锁,展示如何利用模板方法模式来定义锁的行为。

案例类图

定义抽象类 AbstractLock

AbstractLock 提供了模板方法(lockunlock),而具体的处理逻辑是获取锁和释放锁 方法tryAcquiretryRelease,这两个方法的具体实现交由子类完成。

java 复制代码
// 抽象类定义锁的框架
public abstract class AbstractLock {
    // 模板方法:锁的流程固定
    public final void lock() {
        if (!tryAcquire()) { // 尝试获取锁
            waitForLock();   // 获取失败时等待
        }
    }

    // 模板方法:解锁的流程固定
    public final void unlock() {
        if (tryRelease()) { // 尝试释放锁
            notifyWaitingThreads(); // 唤醒等待的线程
        }
    }

    // 钩子方法:尝试获取锁(子类实现)
    protected abstract boolean tryAcquire();

    // 钩子方法:尝试释放锁(子类实现)
    protected abstract boolean tryRelease();

    // 默认行为:等待获取锁(可以覆盖)
    protected void waitForLock() {
        try {
            synchronized (this) {
                wait(); // 阻塞线程
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    // 默认行为:通知等待线程(可以覆盖)
    protected void notifyWaitingThreads() {
        synchronized (this) {
            notifyAll(); // 唤醒所有等待线程
        }
    }
}

实现具体的锁 SimpleLock

SimpleLock 继承了 AbstractLock,并实现了具体的锁逻辑:

java 复制代码
public class SimpleLock extends AbstractLock {
    private boolean isLocked = false; // 锁状态
    private Thread lockingThread = null; // 持有锁的线程

    @Override
    protected synchronized boolean tryAcquire() {
        if (!isLocked) {
            isLocked = true;
            lockingThread = Thread.currentThread();
            return true;
        }
        return false;
    }

    @Override
    protected synchronized boolean tryRelease() {
        if (Thread.currentThread() == lockingThread) {
            isLocked = false;
            lockingThread = null;
            return true;
        }
        return false;
    }
}

测试 SimpleLock

通过多线程模拟锁的使用场景

java 复制代码
public class TemplateLockExample {
    public static void main(String[] args) {
        SimpleLock lock = new SimpleLock();

        Runnable task = () -> {
            lock.lock(); // 获取锁
            try {
                System.out.println(Thread.currentThread().getName() + " acquired the lock");
                Thread.sleep(1000); // 模拟任务执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println(Thread.currentThread().getName() + " released the lock");
                lock.unlock(); // 释放锁
            }
        };

        // 启动多个线程测试锁的互斥
        Thread t1 = new Thread(task, "Thread-1");
        Thread t2 = new Thread(task, "Thread-2");
        Thread t3 = new Thread(task, "Thread-3");

        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果

复制代码
Thread-1 获得锁
Thread-1 释放锁
Thread-3 获得锁
Thread-2 获得锁
Thread-2 释放锁
Thread-3 释放锁

注:该案例并未正确实现完整的锁机制,仅仅为了讲述模版方法模式。

分析

  1. 模板方法的作用lockunlock 方法在 AbstractLock 中定义了锁的固定流程,子类只需实现具体的 tryAcquiretryRelease 方法即可。

  2. 扩展性 :可以通过继承 AbstractLock 实现不同的锁机制,例如:读写锁、可重入锁、公平锁等。

  3. 简化逻辑:模板方法模式将通用逻辑集中在抽象类中,避免子类重复实现。

优缺点和应用场景

优点

  1. 提高代码复用性,通用代码在父类中实现。
  2. 提供扩展灵活性,通过子类覆盖实现具体步骤。
  3. 符合开闭原则,增加新功能时无需修改模板方法。

缺点

  1. 每个具体实现都需要定义子类,导致类数量增加。
  2. 对算法步骤的控制较为严格,可能不适合所有场景。

应用场景

  1. 多个类的逻辑相同但细节不同:公共部分代码抽取到父类,具体实现由子类提供。
  2. 避免代码重复:在模板方法中实现通用逻辑,特定逻辑由子类实现。
  3. 固定框架:需要确保子类遵循算法的基本结构。

模板方法模式的应用

  1. Java中锁的实现(模版类AbstractQueuedSynchronizer,简称AQS),子类(如ReentrantLockReentrantReadWriteLock等)通过继承AQS并实现其抽象方法(如tryAcquiretryRelease等)来完成具体的同步逻辑;
  2. Java Swing 中的框架设计(例如 paint() 方法是一个模板方法);
  3. JUnit 中的测试框架(测试用例继承 TestCase 并重写具体方法)。

总结

在一个抽象类中定义一个模板方法作为算法骨架,其中包含若干通用逻辑和抽象步骤 ,通过子类实现 这些抽象步骤的具体逻辑 ,确保算法流程固定且具有灵活扩展性,同时实现代码复用和行为定制

需要查看往期设计模式文章的,可以在个人主页中或者文章开头的集合中查看,可关注我,持续更新中。。。


超实用的SpringAOP实战之日志记录

2023年下半年软考考试重磅消息

通过软考后却领取不到实体证书?

计算机算法设计与分析(第5版)

Java全栈学习路线、学习资源和面试题一条龙

软考证书=职称证书?

软考中级--软件设计师毫无保留的备考分享

相关推荐
ApeAssistant2 小时前
Spring + 设计模式 (二十) 行为型 - 中介者模式
spring·设计模式
ApeAssistant3 小时前
Spring + 设计模式 (十九) 行为型 - 访问者模式
spring·设计模式
〆、风神3 小时前
从零实现分布式WebSocket组件:设计模式深度实践指南
分布式·websocket·设计模式
前端大白话3 小时前
Vue2和Vue3语法糖差异大揭秘:一文读懂,开发不纠结!
javascript·vue.js·设计模式
前端大白话3 小时前
JavaScript中`Symbol.for()`和`Symbol()`的区别,在创建全局唯一的`Symbol`值时如何选择使用?
前端·javascript·设计模式
CHQIUU4 小时前
Java 设计模式心法之第25篇 - 中介者 (Mediator) - 用“中央协调”降低对象间耦合度
java·设计模式·中介者模式
Pasregret5 小时前
备忘录模式:实现对象状态撤销与恢复的设计模式
运维·服务器·设计模式
碎梦归途7 小时前
23种设计模式-行为型模式之备忘录模式(Java版本)
java·jvm·设计模式·软考·备忘录模式·软件设计师·行为型模式
东阳马生架构15 小时前
Sentinel源码—8.限流算法和设计模式总结二
算法·设计模式·sentinel
冰茶_16 小时前
C#中常见的设计模式
java·开发语言·microsoft·设计模式·微软·c#·命令模式