设计模式:TypeScript中的模板方法模式

如何在 TypeScript 中使用模板方法模式实现可扩展的文件解析器。

欢迎来到 TypeScript 设计模式系列,该系列介绍了使用 TypeScript 进行 Web 开发的一些有用的设计模式。

​之前的文章如下:


设计模式对于 web 开发人员非常重要,掌握它们可以让我们写出更好的代码。在本文中,我将使用 TypeScript 来介绍模板方法模式。

CSV(Comma-Separated Values)是一种通用的、相对简单的文件格式,CSV文件以纯文本的形式存储表格数据(数字和文本),当你需要处理CSV数据时,相应的处理流程如下图所示:

理解了上面的处理流程后,让我们使用 Node.js 来实现解析 csv 文件的功能。

users.csv

id,Name1,Bytefer2,Kakuqo

parse-csv.ts
import fs from "fs";import path from "path";import * as url from "url";import { csvParse } from "d3-dsv";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const processData = (fileData: any[]) => console.dir(fileData);const content = fs.readFileSync(path.join(__dirname, "users.csv"), "utf8");const fileData = csvParse(content);processData(fileData);

在上面的代码中,我们导入了d3-dsv模块来实现csv的解析函数,然后使用esno来执行parse-cvs.ts文件:

$ npx esno parse-csv.ts

当上述代码运行成功时,终端将输出以下结果:

[  { id: Ƈ', Name: 'Bytefer' },  { id: ƈ', Name: 'Kakuqo' },  columns: [ 'id', 'Name' ]]

Markdown是一种轻量级的标记语言,它允许人们以易读易写的纯文本格式编写文档。为了在网页上显示Markdown文档,我们必须将Markdown文档转换为HTML文档。

为了实现上述功能,我们的处理流程如下:

理解了上面的处理流程之后,让我们使用 Node.js 来实现解析 Markdown 文件的功能。

Users.md

### Users- Bytefer- Kakuqo


parse-md.ts

import fs from "fs";import path from "path";import * as url from "url";import { marked } from 'marked'
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const processData = (fileData: any[]) => console.dir(fileData);const content = fs.readFileSync(path.join(__dirname, "Users.md"), "utf8");const fileData = marked.parse(content);processData(fileData);

在上面的代码中,我们导入了 marked 模块来实现 Markdown 文件的解析功能,然后使用 esno 来执行 parse-md.ts 文件:

$ npx esno parse-md.ts

当上述代码运行成功时,终端将输出以下结果:

'<h3 id="users">Users</h3>\n<ul>\n<li>Bytefer</li>\n<li>Kakuqo</li>\n</ul>\n'

对于前面两个示例,尽管解析了不同类型的文件,但您会发现它们的解析过程是相似的。

整个过程主要包括三个步骤:读取文件、解析文件和处理数据,对于该场景,我们可以引入模板方法模式来封装上述三个步骤的处理顺序。

模板方法模式由两个部分组成:一个抽象父类和一个具体的实现子类。通常,子类的算法框架被封装在抽象父类中,它还包括一些公共方法的实现和封装子类中所有方法的执行顺序。通过继承这个抽象类,子类也继承了整个算法结构,并可以选择重载父类的方法。

接下来,让我们看看如何使用模板方法模式实现 CSV 解析器和 Markdown 解析器。

为了更好地理解下面的代码,让我们先看看相应的 UML 类图:

在上图中,我们定义了一个抽象类  FileParser ,然后分别定义了两个子类  CsvParser  和  MarkdownParser 。

FileParser类

abstract class FileParser {  // Template Method  parse(filePath: string) {    let content = this.readFile(filePath);    let fileData = this.parseFile(content);    this.processData(fileData);  }  readFile(filePath: string) {    if (fs.existsSync(filePath)) {      return fs.readFileSync(filePath, "utf8");    }  }  abstract parseFile(fileContent: string): any;  processData(fileData: any[]) {    console.log(fileData);  }}

抽象类 FileParser 中的 parse 方法是所谓的模板方法,我们在这个方法中封装了文件处理的过程。

CsvParser类

class CsvParser extends FileParser {  parseFile(fileContent: string) {    return csvParse(fileContent);  }}


MarkdownParser 类

class MarkdownParser extends FileParser {  parseFile(fileContent: string) {    return marked.parse(fileContent);  }}

有了  CsvParser  和  MarkdownParser  这两个类,我们可以用以下方式解析 CSV 和 Markdown 文件:

const csvParser = new CsvParser();csvParser.parse(path.join(__dirname, "Users.csv"));
const mdParser = new MarkdownParser();mdParser.parse(path.join(__dirname, "Users.md"));

当你成功运行上述代码时,相应的输出如下图所示:

使用模板方法模式,我们重新实现了对 CSV 和 Markdown 文件的解析,实际上,通过抽象类  FileParser ,我们可以轻松地开发不同的文件解析器。

最后,让我们总结一下模板方法模式的使用场景:

  • 算法的整体步骤非常固定,但当个别部分是可变的时,此时可以使用模板方法模式来抽象易变部分,以便子类实现。

 欢迎关注公众号:文本魔术,了解更多

  • 28
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值