Vite CLI 也用了命令模式?
欢迎你阅读 「《重学 TypeScript 3.0》」 系列教程,本系列教程会包含 TypeScript 基础知识、进阶知识、类型体操(精选)、设计模式、核心特性实战和开源项目源码解析 「6」 大专题的内容。
在富文本编辑器和 CLI 应用程序的场景中,经常遇到命令模式的身影。跟策略模式一样,命令模式也是属于行为模式。本文阿宝哥将带大家一起来学习命令模式。
在 iOS 和 macOS 上,有一个内置的「快捷指令」应用程序。使用该应用程序,用户可以快速执行一项或多项任务。比如,快速发送消息、翻译文本、缩短 URL 和下载文件等任务。
下面我们来实现一个能满足上述功能的应用程序。首先,阿宝哥定义了一个 Shortcuts
类,在类中定义了 openUrl
、 shortenUrl
、sendMessage
等 5 个成员方法。
class Shortcuts {
openUrl(url: string) { // 打开指定链接
console.log(`Open url: ${url}`);
}
shortenUrl(url: string) { // 缩短指定链接
console.log(`Shorten url: ${url}`);
}
sendMessage(msg: string) { // 发送消息
console.log(`Send message: ${msg}`);
}
translateText(originText: string) { // 翻译文本
console.log(`Translate text: ${originText}`);
}
downloadFile(fileUrl: string) { // 下载指定文件
console.log(`Download file: ${fileUrl}`);
}
}
有了 Shortcuts
类之后,我们继续定义一个 UIEventHandler
类,该类包含了一个 handleAction
成员方法,用于处理用户的行为。
class UIEventHandler {
constructor(public shortcuts: Shortcuts) {}
handleAction(action: ShortcutsMethods, arg: string) {
this.shortcuts[action](arg);
}
}
// "openUrl" | "shortenUrl" | "sendMessage" | "translateText" | "downloadFile"
type ShortcutsMethods = Methods<Shortcuts>;
type Methods<T> = {
[P in keyof T]: T[P] extends (...args: any) => void ? P : never;
}[keyof T];
handleAction
方法接收 action
和 arg
2 个参数,其中 action
的类型是 ShortcutsMethods
。该类型是通过 Methods
工具类型生成的,在 Methods
工具类型内部,阿宝哥使用了 TypeScript(mapped types)中的映射类型。如果你对 TypeScript 映射类型还不熟悉的话,推荐你阅读 “用了 TS 映射类型,同事直呼内行!” 这篇文章。
创建完 UIEventHandler
类之后,我们可以通过以下方式来使用它:
const shortcuts = new Shortcuts();
const eventHandler = new UIEventHandler(shortcuts);
eventHandler.handleAction("openUrl", "https://github.com/semlinker");
eventHandler.handleAction("sendMessage", "Hello Semlinker!");
对于上述的代码,看起来好像没有什么问题。但仔细分析后,你会发现存在以下问题:
在调用 handleAction
方法时,我们需要保证 action 的名称与Shortcuts
对象所关联的方法名称一致;随着功能的不断增加, Shortcuts
类中的方法也会不断增加,我们就需要不断修改Shortcuts
类。
那么我们应该如何解决上述问题呢?对于这个问题,我们可以使用命令模式。为了让大家能够更好地理解命令模式的相关代码,我们先来看一下对应的 UML 图:
❝提示:Android 平台 1 元 10 个微豆,iOS 平台 1 元 7 个微豆,购买时可切换平台充值。
❞