策略模式
大约 1 分钟
引入
我们有着这么一个 login
方法, 主要处理 登录逻辑
const login = (mode: string) => {
if (mode === 'account') {
loginWithAccount();
} else if (mode === 'email') {
loginWithEmial();
} else if (mode === 'github') {
loginWithGithub();
} else if (mode === 'mobile') {
loginWithMobie();
} else if (mode === 'weChat') {
loginWithWeChat();
} else if (mode === 'weibo') {
loginWithWeibo();
} else if (mode === 'qq') {
loginWithQQ();
} else {
throw new Error('not support mode:' + mode);
}
};
随着 mode
的值越来越多, login
越来越臃肿, if...else...
嵌套的越深,
针对以上的问题 我们可以 使用 策略模式
策略模式
策略模式主要有三部分组成
- Context: 持有策略类的引用
- Strategy: 抽象的角色, 通常是一个接口或者抽象类
- ConcreteStrategy: 具体策略角色, 封装了相关的算法或者行为
提示
策略模式 在 vue2.x 源码里面也用到过
interface Strategy {
authenticate(args: any[]): boolean;
}
class LocalStrategy implements Strategy {
authenticate(args: any[]) {
const [username, password] = args;
// 验证用户名密码的操作
}
}
class WeChatStrategy implements Strategy {
authenticate(args: any[]) {
const [token] = args;
// 验证token
}
}
// qq/weibo/github 类似
class AuthContext {
strategies: Record<string, Strategy>; // Context 存储策略的集合
use(name: string, strategy: Strategy) {
// 注册 策略
this.strategies[name] = strategy;
}
authenticate(name: string, ...args: any[]) {
if (!this.strategies[name]) {
console.error('unknown strategy: ' + name);
return false;
}
return this.strategies[name].authenticate.apply(null, args);
}
}
重构 login
const auth = new AuthContext();
auth.use('weChat', new WeChatStrategy());
auth.use('account', new LocalStrategy());
const login = (mode: string, ...args: any[]) => {
return auth.authenticate(mode, args);
};