当前位置: 首页 > news >正文

【设计模式精解】从根上理解模板方法设计模式及其应用

目录

模板方法模式有哪些应用?

概念

模板方法设计模式之前是怎么写代码的?

代码示例

代码结构图

模板方法设计模式样例

UML类图

代码示例

AQS是怎么应用模板方法设计模式的?

acquire()具体是什么流程呢?

模板方式设计模式的优缺点


模板方法模式有哪些应用?

在很多时候,我们的代码中可能会有一些公共的部分并且还有一些定制的部分,那么公共这部分就可以定义在一个父类中,然后将定制的部分实现在子类中。这样子类可以根据需要扩展或重写父类的方法,而不需要改变算法的结构。

概念

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤,这种类型的设计模式属于行为型模式。

模板方法设计模式之前是怎么写代码的?

代码示例

以一个试卷为例,每个学生都需要把试卷上的题目抄一遍并且选择答案,代码如下:

public class PaperA {// 试题一public void question1() {System.out.println("第一题的题目是:1+1=?");System.out.println("第一题的答案选择" + "A");}// 试题二public void question2() {System.out.println("第二题的题目是1+2=?");System.out.println("第二题的答案选择" + "B");}// 试题三public void question3() {System.out.println("第三题的题目是1+3=?");System.out.println("第三题的答案选择" + "C");}
}
public class PaperB {// 试题一public void question1() {System.out.println("第一题的题目是:1+1=?");System.out.println("第一题的答案选择" + "B");}// 试题二public void question2() {System.out.println("第二题的题目是1+2=?");System.out.println("第二题的答案选择" + "D");}// 试题三public void question3() {System.out.println("第三题的题目是1+3=?");System.out.println("第三题的答案选择" + "A");}
}
public class Client {public static void main(String[] args) {System.out.println("学生甲的试卷-------------");PaperA paperA = new PaperA();paperA.question1();paperA.question2();paperA.question3();System.out.println("学生乙的试卷-------------");PaperB paperB = new PaperB();paperB.question1();paperB.question2();paperB.question3();}
}

可以感觉到学生甲和学生乙两个抄试卷类非常类似,除了答案不同,没什么不一样的,假设老师突然要改代码,如果某人抄错了,那就糟糕了。

所以我们的解决办法是老师出一根试卷,打印多份,让学生写答案就行。也就是抽象出一个父类,让两个子类继承,公共的试题代码写到父类当中就可以,下面我来写写看。

// 抽象父类
public abstract class Paper {public void question1() {System.out.println("第一题的题目是1+1=?");System.out.println("第一题的答案选择" + answer1());}// 子类需要重写的方法public abstract String answer1();public void question2() {System.out.println("第二题的题目是1+2=?");System.out.println("第二题的答案选择" + answer2());}// 子类需要重写的方法public abstract String answer2();public void question3() {System.out.println("第三题的题目是1+3=?");System.out.println("第三题的答案选择" + answer3());}// 子类需要重写的方法public abstract String answer3();
}
public class PaperA extends Paper {@Overridepublic String answer1() {return "A";}@Overridepublic String answer2() {return "B";}@Overridepublic String answer3() {return "C";}
}
public class PaperB extends Paper {@Overridepublic String answer1() {return "B";}@Overridepublic String answer2() {return "D";}@Overridepublic String answer3() {return "A";}
}

客户端程序

public class Client {public static void main(String[] args) {System.out.println("学生甲的试卷-------------");PaperA paperA = new PaperA();paperA.question1();paperA.question2();paperA.question3();System.out.println("学生乙的试卷-------------");PaperB paperB = new PaperB();paperB.question1();paperB.question2();paperB.question3();}
}

代码结构图

模板方法设计模式样例

UML类图

代码示例

// 抽象类,定义模板方法
public abstract class AbstractClass {// 模板方法,定义了算法的主要步骤public final void templateMethod() {primitiveOperation1(); // 调用第一个具体步骤primitiveOperation2(); // 调用第二个具体步骤}// 抽象方法,由子类实现protected abstract void primitiveOperation1();// 抽象方法,由子类实现protected abstract void primitiveOperation2();
}// 子类A,实现抽象方法
public class ClassA extends AbstractClass {@Overrideprotected void primitiveOperation1() {// 实现具体步骤A1System.out.println("ClassA primitiveOperation1");}@Overrideprotected void primitiveOperation2() {// 实现具体步骤A2System.out.println("ClassA primitiveOperation2");}
}// 子类B,实现抽象方法
public class ClassB extends AbstractClass {@Overrideprotected void primitiveOperation1() {// 实现具体步骤B1System.out.println("ClassB primitiveOperation1");}@Overrideprotected void primitiveOperation2() {// 实现具体步骤B2System.out.println("ClassB primitiveOperation2");}
}

客户端程序

// 客户端代码
public class Client {public static void main(String[] args) {AbstractClass classA = new ClassA();classA.templateMethod(); // 输出:ClassA primitiveOperation1, ClassA primitiveOperation2AbstractClass classB = new ClassB();classB.templateMethod(); // 输出:ClassB primitiveOperation1, ClassB primitiveOperation2}
}

AQS是怎么应用模板方法设计模式的?

AQS是一个抽象类,它内部定义了一些公共的方法,这些公共的方法有获取锁acquire(),还有释放锁release()、等方法。也就是把这个架子搭好了,你自己用的时候需要让子类继承这个抽象类然后重写tryAcquire(),tryRelease()方法,这就是一个典型的模板方法的应用。

AQS类中 , 公共方法描述
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
独占获取的同步状态
它调用了子类重写的tryAcquire方法,如果获取成功,直接返回,否则接着走其他方法进度等待队列
public final boolean release(int arg) {
        if (tryRelease(arg)) {
                Node h = head;
                if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
                return true;
        }
        return false;
}
独占式释放同步状态
释放成功后,把同步队列中第一个节点内的线程唤醒

acquire()具体是什么流程呢?

就是if里的方法的执行顺序:
tryAcquire()--->addWaiter(Node.EXCLUSIVE)--------------------->acquireQueued(##,arg)-------------------------->selfInterrupt()

获取锁--------->获取失败后,请求锁的线程包装成Node,放入队列--->刚包装成Node的线程,让它尝试获取锁或挂起---->中断当前线程

整合一下上面的图:

Semaphore 的重写方法

public boolean tryAcquire(int permits) {if (permits < 0) throw new IllegalArgumentException();return sync.nonfairTryAcquireShared(permits) >= 0;
}

模板方式设计模式的优缺点

优点:尽可能的将重复的代码提升带父类中去,子类只描述特化的那一部分代码。大大降低代码的重复度。
缺点:父类与子类之间的调用关系复杂,增加了代码阅读难度;通过继承实现,如果父类添加新的抽象方法,所有子类都需要修改。

如果我的内容对你有帮助,请辛苦动动您的手指为我点赞,评论,收藏。感谢大家。

http://www.dtcms.com/a/317395.html

相关文章:

  • RN项目环境搭建和使用-Mac版本(模拟器启动不起来的排查)
  • Python虚拟环境完全指南:pyenv vs venv 在macOS上的使用详解
  • Mac安装WebStorm
  • java中Reflection反射(一)
  • MCU AI/ML - 弥合智能和嵌入式系统之间的差距
  • Java猜数字简易小游戏可复制
  • qt6 cmake vscode加载qrc图片资源
  • vue3 el-select el-option 使用
  • 批量打印Excel条形码
  • Linux入门DAY18
  • 单变量单步时序预测:CNN-GRU卷积神经网络结合门控循环单元
  • EasyExcel高效工具类:简化Excel导入导出,支持多Sheet与枚举转换
  • 基于CentOS-7.6部署k8s-1.24.0,containerd作为CRI,nerdctl作为容器管理CLI
  • Datawhale AI 夏令营 让AI读懂财报PDF(多模态RAG)202508
  • bool 类型转换运算符重载
  • WordPress自定义.js文件排序实现方法
  • CSS :is () 与 :where ():简化复杂选择器的 “语法糖”
  • 凸优化:鞍点和对偶停止设计准则
  • 基于PHP的快递管理系统的设计与实现
  • 利用C++11和泛型编程改进原型模式
  • 开发笔记 | 接口与抽象基类说明以及对象池的实现
  • SpringBoot 3.x整合Elasticsearch:从零搭建高性能搜索服务
  • JSON巴巴 - 专业JSON格式化工具:让任何JSON都能完美格式化
  • 基于 Jenkins Pipeline 实现 DITA 文档自动化构建与发布(开源方案)
  • Jenkinsfile各指令详解
  • 国民技术N32G003实现PMBus从机及使用STM32F103模拟I2C主机访问从机
  • PostgreSQL 通配符指南:解锁 LIKE 查询的魔法 - % 与 _ 详解
  • 区块链技术在供应链管理中的应用案例
  • C语言的综合案例
  • HIVE 窗口函数处理重复数据