查看原文
其他

Vite CLI 也用了命令模式?

阿宝哥 全栈修仙之路 2023-03-11

欢迎你阅读 「《重学 TypeScript 3.0》」 系列教程,本系列教程会包含 TypeScript 基础知识、进阶知识、类型体操(精选)、设计模式、核心特性实战和开源项目源码解析 「6」 大专题的内容。

在富文本编辑器和 CLI 应用程序的场景中,经常遇到命令模式的身影。跟策略模式一样,命令模式也是属于行为模式。本文阿宝哥将带大家一起来学习命令模式。

在 iOS 和 macOS 上,有一个内置的「快捷指令」应用程序。使用该应用程序,用户可以快速执行一项或多项任务。比如,快速发送消息、翻译文本、缩短 URL 和下载文件等任务。

下面我们来实现一个能满足上述功能的应用程序。首先,阿宝哥定义了一个 Shortcuts 类,在类中定义了 openUrlshortenUrlsendMessage 等 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 方法接收 actionarg 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 个微豆,购买时可切换平台充值。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存