策略模式原来这么简单!
欢迎你阅读 「《重学 TypeScript 3.0》」 系列教程,本系列教程会包含 TypeScript 基础知识、进阶知识、类型体操(精选)、设计模式、核心特性实战和开源项目源码解析 「6」 大专题的内容。
近期团队内招聘高级前端,阿宝哥跟挺多候选人聊过,发现大多数候选人对前端常用设计模式的理解还不够深,所以阿宝哥决定先更新 「TypeScript 设计模式」 专题。本文阿宝哥将带大家一起来学习工作中,非常有用的设计模式 —— 「策略模式」。
在 Web 应用中,注册和登录是很重要的功能。在注册 Web 应用的账号时,主流的 Web 应用一般会提供不同的注册方式。比如,用户名/密码、邮箱、手机号码或第三方账号(微信/微博账号等)。当你成功注册账号之后,大多数 Web 应用还会引导你完善个人资料。在此期间,如果你绑定了其它的登录方式,那么在登录时你就可以选择不同的登录方式。要实现登录时,支持切换不同登录方式的功能,我们可以定义一个 login
函数:
function login(mode) {
if (mode === "account") {
loginWithAccount();
} else if (mode === "email") {
loginWithEmail();
} else if (mode === "mobile") {
loginWithMobile();
}
}
但如果 Web 应用还要支持微信、微博或 Github 等第三方平台的登录方式。我们就需要修改前面定义的 login
函数:
function login(mode) {
if (mode === "account") {
loginWithAccount(); // 账号/密码
} else if (mode === "email") {
loginWithEmail(); // 邮箱/密码
} else if (mode === "mobile") {
loginWithMobile(); // 手机号/验证码
} else if (mode === "wechat") {
loginWithWechat(); // 微信账号
} else if (mode === "weibo") {
loginWithWeibo(); // 微博账号
} else if (mode === "github") {
loginWithGithub(); // Github 账号
} else {
throw new Error(`Unsupported login mode: ${mode}`);
}
}
之后,我们可能还要添加其它的登录方式或修改原有的登录方式,这时我们就会发现 login
函数变得越来越臃肿。针对这个问题,我们可以使用策略模式,将不同的登录方式封装成不同的登录策略。这样不仅可以避免使用一堆的 if...else
语句,同时还能满足后期不断扩展的需求。
下面阿宝哥将使用 TypeScript 来演示如何利用 「策略模式」 来解决上述的问题。策略模式主要由以下 3 个角色组成:
Context:持有策略类的引用,提供给客户端使用; Strategy:抽象的角色,通常是一个接口或抽象类; ConcreteStrategy:具体策略角色,封装了相关的算法和行为。
在前面的登录场景中,阿宝哥将定义一个 Authenticator
类来管理不同的登录策略,它对应于策略模式中的 Context
角色。接着使用 interface
定义一个 Strategy
接口,然后基于该接口实现 「账号/密码」 和 「微信登录」 两种不同的登录策略。
为了更好的理解下面的代码,我们先来看一下对应的 UML 图:
❝提示:Android 平台 1 元 10 个微豆,iOS 平台 1 元 7 个微豆,购买时可切换平台充值。
❞