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

第十六章 模板方法模式

目录

1 模板方法模式介绍

2 模板方法模式原理

3 模板方法模式实现

 4 模板方法模式应用实例

5 模板方法模式总结


1 模板方法模式介绍

模板方法模式(template method pattern)原始定义是:在操作中定义算法的框架,将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。

模板方法的作用主要是提高程序的复用性和扩展性:

  • 复用指的是,所有的子类可以复用父类中提供的模板方法代码
  • 扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能.

2 模板方法模式原理

模板方法(Template Method)模式包含以下主要角色:

  • 抽象父类:定义一个算法所包含的所有步骤,并提供一些通用的方法逻辑。
  • 具体子类:继承自抽象父类,根据需要重写父类提供的算法步骤中的某些步骤。

抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。

  • 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。

  • 基本方法:是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:

    • 抽象方法(Abstract Method) :一个抽象方法由抽象类声明、由其具体子类实现。

    • 具体方法(Concrete Method) :一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。

    • 钩子方法(Hook Method) :在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。

      一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXxx,返回值类型为boolean类型。

3 模板方法模式实现

/*** 抽象父类* @author spikeCong* @date 2022/10/12**/
public abstract class AbstractClassTemplate {void step1(String key){System.out.println("在模板类中 -> 执行步骤1");if(step2(key)){step3();}else{step4();}step5();}boolean step2(String key){System.out.println("在模板类中 -> 执行步骤2");if("x".equals(key)){return true;}return false;}abstract void step3();abstract void step4();void step5(){System.out.println("在模板类中 -> 执行步骤5");}void run(String key){step1(key);}}public class ConcreteClassA extends AbstractClassTemplate{@Overridevoid step3() {System.out.println("在子类A中 -> 执行步骤 3");}@Overridevoid step4() {System.out.println("在子类A中 -> 执行步骤 4");}
}public class ConcreteClassB extends AbstractClassTemplate {@Overridevoid step3() {System.out.println("在子类B中 -> 执行步骤 3");}@Overridevoid step4() {System.out.println("在子类B中 -> 执行步骤 4");}
}public class Test01 {public static void main(String[] args) {AbstractClassTemplate concreteClassA = new ConcreteClassA();concreteClassA.run("");System.out.println("===========");AbstractClassTemplate concreteClassB = new ConcreteClassB();concreteClassB.run("x");}
}// 输出结果
在模板类中 -> 执行步骤1
在模板类中 -> 执行步骤2
在子类A中 -> 执行步骤 4
在模板类中 -> 执行步骤5
===========
在模板类中 -> 执行步骤1
在模板类中 -> 执行步骤2
在子类B中 -> 执行步骤 3
在模板类中 -> 执行步骤5

 4 模板方法模式应用实例

/*** 账户抽象类* @author spikeCong* @date 2022/10/12**/
public abstract class Account {//step1 具体方法-验证用户信息是否正确public boolean validate(String account,String password){System.out.println("账号: " + account + ",密码: " + password);if(account.equalsIgnoreCase("tom") &&password.equalsIgnoreCase("123456")){return true;}else{return false;}}//step2 抽象方法-计算利息public abstract void calculate();//step3 具体方法-显示利息public void display(){System.out.println("显示利息!");}//模板方法public void handle(String account,String password){if(!validate(account,password)){System.out.println("账户或密码错误!!");return;}calculate();display();}
}/*** 借款一个月* @author spikeCong* @date 2022/10/12**/
public class LoanOneMonth extends Account{@Overridepublic void calculate() {System.out.println("借款周期30天,利率为10%!");}
}/*** 借款七天* @author spikeCong* @date 2022/10/12**/
public class LoanSevenDays extends Account{@Overridepublic void calculate() {System.out.println("借款周期7天,无利息!仅收取贷款金额1%的服务费!");}@Overridepublic void display() {System.out.println("七日内借款无利息!");}}public class Client {public static void main(String[] args) {Account a1 = new LoanSevenDays();a1.handle("tom","12345");System.out.println("==========================");Account a2 = new LoanOneMonth();a2.handle("tom","123456");}
}

5 模板方法模式总结

优点:

  • 在父类中形式化的定义一个算法,而由它的子类来实现细节处理,在子类实现详细的处理代码时,并不会改变父类算法中步骤的执行顺序.

  • 模板方法可以实现一种反向的控制结构,通过子类覆盖父类的钩子方法,来决定某一个特定步骤是否需要执行

  • 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则.

缺点:

  • 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
  • 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

模板方法模式的使用场景一般有:

  • 多个类有相同的方法并且逻辑可以共用时;
  • 将通用的算法或固定流程设计为模板,在每一个具体的子类中再继续优化算法步骤或流程步骤时;
  • 重构超长代码时,发现某一个经常使用的公有方法。

相关文章:

  • 上海媒体宣传:上海展览展会媒体邀约宣传怎么做?
  • Python深度学习:Bi-LSTM和LSTM在网络上有什么区别,对比来看
  • web前端需要的知识点:深度解析与技能进阶之路
  • Vue——子级向父级使用props传递数据(函数)
  • Golang | Leetcode Golang题解之第137题只出现一次的数字II
  • FPGA SPI采集ADC7606数据
  • OKCC系统之编解码转码
  • 备战 清华大学 上机编程考试-冲刺前50%,倒数第3天
  • 小程序使用接口wx.getLocation配置
  • git 常用的命令
  • 【perfetto分析性能学习笔记】
  • eNSP学习——配置高级的访问控制列表
  • 计算机网络时延计算的单位换算问题
  • SpringCloud专题
  • canvas的使用方法
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • co.js - 让异步代码同步化
  • If…else
  • iOS编译提示和导航提示
  • javascript从右向左截取指定位数字符的3种方法
  • Java多线程(4):使用线程池执行定时任务
  • leetcode98. Validate Binary Search Tree
  • PHP变量
  • REST架构的思考
  • Vim Clutch | 面向脚踏板编程……
  • 初识 webpack
  • 当SetTimeout遇到了字符串
  • 解决iview多表头动态更改列元素发生的错误
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 面试遇到的一些题
  • 前嗅ForeSpider采集配置界面介绍
  • 手机端车牌号码键盘的vue组件
  • 新书推荐|Windows黑客编程技术详解
  • FaaS 的简单实践
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 容器镜像
  • ​configparser --- 配置文件解析器​
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • # 安徽锐锋科技IDMS系统简介
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • ( 10 )MySQL中的外键
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (理论篇)httpmoudle和httphandler一览
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)为C# Windows服务添加安装程序
  • .cfg\.dat\.mak(持续补充)
  • .jks文件(JAVA KeyStore)
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .Net 6.0 处理跨域的方式