掌握设计模式--模板方法模式
创作时间:
作者:
@小白创作中心
掌握设计模式--模板方法模式
引用
1
来源
1.
https://www.cnblogs.com/dennyLee2025/p/18793921
模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个操作中的算法骨架,并允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
核心思想:模板方法定义算法骨架,浅白地说,定义通用的逻辑框架、控制流程和调用顺序,而具体的实现将延迟到子类,从而在不改变结构的前提下扩展算法的灵活性。再简单点说:定义了一个处理逻辑的步骤(一个骨架),具体的处理逻辑由子类继承后实现(真正的血肉)。
主要组成部分
- 抽象类(AbstractClass):
- 定义模板方法,模板方法包含算法的骨架。
- 实现一些不变的步骤,或声明需要子类实现的抽象方法。
- 具体类(ConcreteClass):
- 实现抽象类中声明的抽象方法,从而完成算法的具体步骤。
案例实现
实现一个简单的自定义锁,展示如何利用模板方法模式来定义锁的行为。
案例类图
定义抽象类
AbstractLock提供了模板方法(lock和unlock),而具体的处理逻辑是获取锁和释放锁方法tryAcquire和tryRelease,这两个方法的具体实现交由子类完成。
// 抽象类定义锁的框架
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继承了AbstractLock,并实现了具体的锁逻辑:
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;
}
}
测试
通过多线程模拟锁的使用场景:
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 acquired the lock
Thread-1 released the lock
Thread-3 acquired the lock
Thread-2 acquired the lock
Thread-2 released the lock
Thread-3 released the lock
注:该案例并未正确实现完整的锁机制,仅仅为了讲述模版方法模式。
分析
- 模板方法的作用:
lock和unlock方法在AbstractLock中定义了锁的固定流程,子类只需实现具体的tryAcquire和tryRelease方法即可。 - 扩展性:可以通过继承
AbstractLock实现不同的锁机制,例如:读写锁、可重入锁、公平锁等。 - 简化逻辑:模板方法模式将通用逻辑集中在抽象类中,避免子类重复实现。
优缺点和应用场景
优点
- 提高代码复用性,通用代码在父类中实现。
- 提供扩展灵活性,通过子类覆盖实现具体步骤。
- 符合开闭原则,增加新功能时无需修改模板方法。
缺点
- 每个具体实现都需要定义子类,导致类数量增加。
- 对算法步骤的控制较为严格,可能不适合所有场景。
应用场景
- 多个类的逻辑相同但细节不同:公共部分代码抽取到父类,具体实现由子类提供。
- 避免代码重复:在模板方法中实现通用逻辑,特定逻辑由子类实现。
- 固定框架:需要确保子类遵循算法的基本结构。
模板方法模式的应用
- Java中锁的实现(模版类
AbstractQueuedSynchronizer,简称AQS),子类(如ReentrantLock、ReentrantReadWriteLock等)通过继承AQS并实现其抽象方法(如tryAcquire、tryRelease等)来完成具体的同步逻辑; - Java Swing中的框架设计(例如
paint()方法是一个模板方法); - JUnit中的测试框架(测试用例继承
TestCase并重写具体方法)。
总结
在一个抽象类中定义一个模板方法作为算法骨架,其中包含若干通用逻辑和抽象步骤,通过子类实现这些抽象步骤的具体逻辑,确保算法流程固定且具有灵活扩展性,同时实现代码复用和行为定制。
热门推荐
西南财经大学:中国顶尖财经类高校
志愿军的"三三制"战术:远超日军"人海战术"的精锐步兵战法
揭秘:秦始皇统一六国的3大因素,缺了“他”秦始皇不可能成功
哪吒怎么画?掌握哪吒的特点,只需4步,画哪吒更好看
10首五言绝句,短小精悍,看着不说话,就十分美好
德国中产阶级分析:纷纷背离现任政府
扬帆启航:小学英语单词词汇量积累的五大秘籍
施工合同违约了怎么处罚
《原神》元素反应组合攻略:详解最佳战斗策略
培哚普利片正确使用的说明
琼瑶小说中的女性角色命名艺术,及其背后的文化意蕴
文旅融合贺佳节:在邯郸道上品成语韵味
发几个“哈”才算有礼貌?文字为啥越来越廉价了……
《孤岛惊魂5》合作模式全任务速通技巧:团队协作与任务分配
女孩在武校学习武术好吗?
什么水果适合做冷萃咖啡特调?黑咖啡加奶用什么比例合适?
掌握血压测量时机,守护心血管健康
工信部发布电动车“白名单”,四大品牌率先入选!
【食谱】韩式料理大全:10道经典韩式料理在家就能轻松做
明日方舟干员养成攻略:从招募到精英化的全方位指南
宋庆龄幼儿园:设计一周菜单的项目化学习案例
身上有五万怎么赚?如何合理利用五万元进行投资?
三分法则:迷人照片构图的秘密
黄芪和枸杞泡水喝有什么作用
杜牧诗歌的艺术特色与历史价值
当女生说“我来姨妈了”,你会怎么做?
在线测试答题系统
C语言如何声明其他文件的函数
用Notion搭建人生操作系统
从人情社会中看宋史,从细节中窥探真实