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

【模板方法】设计模式:构建可扩展软件的基石

本文主要介绍模板方法设计模式的定义、作用及使用场景

引言

在软件开发中,设计模式是解决常见问题的经过验证的解决方案。模板方法设计模式,作为行为型设计模式的一种,提供了一种在不牺牲灵活性的前提下定义算法框架的方法。
本文将深入探讨模板方法设计模式,包括其定义、结构、应用场景、优缺点以及实际案例分析。

定义

模板方法模式在一个方法中定义了一个算法框架,将一些步骤延迟到子类中实现。它使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。

模式结构

模板方法模式通常包含以下角色:

  • 抽象类(Abstract Class):定义了模板方法和一些基本方法(包括钩子方法和抽象方法)。
  • 具体类(Concrete Class):继承自抽象类并实现抽象方法。
public abstract class AbstractClass{public final void templateMethod(){// ... do somethingmethod1();// ... do somethingmethod2();// ... do something}protected abstract void method1();protected abstract void method2();
}public class ActionClass1 extends AbstractClass{@Overrideprotected void method1(){// ... do something}@Overrideprotected void method2(){// ... do something}
}
public class ActionClass2 extends AbstractClass{@Overrideprotected void method1(){// ... do something}@Overrideprotected void method2(){// ... do something}
}AbstractClass demo = new ActionClass1();
demo.templateMethod();

作用

复用

在模板方法中,将可变的部分留给子类去实现,所有的子类都可以复用父类中模板方法所定义的流程代码。
比如最常见的 InputStream,就用到了模板方法设计模式。


public abstract class InputStream implements Closeable {//...省略其他代码.../**模板方法,定义了读取数据的整个流程,且暴露了一个由子类去实现的抽象方法read()*/public int read(byte b[], int off, int len) throws IOException {if (b == null) {throw new NullPointerException();} else if (off < 0 || len < 0 || len > b.length - off) {throw new IndexOutOfBoundsException();} else if (len == 0) {return 0;}int c = read();if (c == -1) {return -1;}b[off] = (byte)c;int i = 1;try {for (; i < len ; i++) {c = read();if (c == -1) {break;}b[off + i] = (byte)c;}} catch (IOException ee) {}return i;}public abstract int read() throws IOException; //子类去实现
}public class ByteArrayInputStream extends InputStream {//...省略其他代码...@Overridepublic synchronized int read() {return (pos < count) ? (buf[pos++] & 0xff) : -1;}
}

扩展

模板方法设计模式常用在框架的开发中,让框架的使用者可以在不修改框架源码的情况下,定制框架的功能。
比如HttpServletservice()方法就是一个模板方法,它实现了整个Http请求的执行流程,doGetdoPost是模板中可以由子类来定制的部分。

protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException
{String method = req.getMethod();if (method.equals(METHOD_GET)) {long lastModified = getLastModified(req);if (lastModified == -1) {doGet(req, resp);} else {long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);if (ifModifiedSince < lastModified) {maybeSetLastModified(resp, lastModified);doGet(req, resp);} else {resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}} else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} else if (method.equals(METHOD_POST)) {doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req,resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req,resp);} else {String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);}
}

优点

  • 高度的代码复用:通过共享不变的算法骨架,减少代码重复。
  • 灵活性与扩展性:子类可以在不改变算法结构的前提下,提供特定步骤的实现。
  • 松耦合:算法的骨架与具体实现解耦,提高了系统的可维护性。

应用场景

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

  • 多步骤算法:需要执行一系列固定顺序的步骤,但某些步骤的具体实现可能不同。
  • 相似行为的家族:一组类具有相似的行为,但具体实现有所不同。
  • 需要控制扩展:希望控制子类的扩展,同时保持算法结构的一致性。

实战

关于实战内容,我将在后续的文章中来详述一下,我当时怎么利用模板方法设计模式+责任链设计模式来优化系统性能的。
今天,我只简单的聊一下,当时的背景是怎样的,为什么要进行系统优化。

背景

当时我负责的那个系统是财务系统,对财务熟悉的人应该知道,财务系统特别复杂,且在月初的时候需要进行账务核算。

在进行账务核算的时候,需要执行 10 个步骤,每一个步骤都是去登录不同的平台去执行。

  1. 登录应用服务器 1,执行 curl 命令;
  2. 登录数据库服务器,执行 sql;
  3. 登录应用服务器 2,执行 curl 命令;
  4. 用 postman 调用 python 接口。

只有当这 10 个步骤串行执行成功后,整个结账流程才算结束。
最开始负责这部分的同事,纯手工执行这 10 个步骤的,麻烦不说且十分耗时。

等我接手之后,对此进行了改造。
我们认真分析一下可以看出来,从步骤 1 到步骤 10 的执行,这不就很符合调度链吗,而且每一个步骤的执行都需要依赖前一个步骤执行成功且自己是未执行的状态,这不就是一个模板吗。

更详细的内容,我将作为一个单独的文章,更详细的展示出来。

结论与最佳实践

模板方法设计模式是一种强大的设计工具,它通过定义算法的骨架,提供了一种灵活而一致的方式来扩展系统。
在实际应用中,应该仔细考虑何时使用模板方法模式,以及如何设计抽象类和具体类,以确保系统的可维护性和可扩展性。


http://www.mrgr.cn/news/8431.html

相关文章:

  • JetBrains Rider 2024.2 (macOS, Linux, Windows) - 快速且强大的跨平台 .NET IDE
  • SpringCache源码解析(一)
  • 使用 Tailwind CSS 实现水平和垂直居中对齐的方法
  • 【学习笔记】NTN技术整理
  • Objective-C 动态调用秘籍:NSInvocation 的魔法
  • Mako 模板语言
  • (南京观海微电子)——直流电源使用介绍
  • 基于Python的网易民谣歌词数据分析的设计与实现
  • 广州网站制作seo优化技巧
  • C语言01 每日一练01
  • 模型 FIRE沟通法
  • 混合A*算法
  • SpringBoot集成kafka接收消息
  • 在网易云音乐服务器故障事件中提升应急处理能力的探讨
  • 分发糖果
  • jom.exe 是一个并行构建工具,专门为使用 Microsoft Visual C++ 编译器的 Qt 项目加速编译过程
  • 【数据结构篇】~二叉树(堆)
  • 使用Python恢复Windows、Linux、MacOS回收站中的文件和目录
  • Windows与Linux的和谐共处时代!
  • 目标 CDC实例数据库更改密码,预定启动报错SQL 错误代码为“-30082”。SQL 状态为:08001。