TypeScript设计模式:策略模式

策略模式(Strategy Pattern)是一种行为设计模式,用于定义一系列算法,让它们可以相互替换,并且算法的变化不会影响使用算法的客户端。在身份认证系统中,策略模式常用于支持多种认证方式(如JWT、Basic Auth),以实现灵活性和可扩展性。

设计模式原理

策略模式通过将变化的算法部分提取到独立的策略类中,由上下文类动态选择和执行具体策略。这样可以实现:

  • 单一职责:每个策略类只负责一种算法实现,上下文负责协调。
  • 灵活性:支持运行时切换算法,无需修改上下文代码。
  • 开闭原则:对扩展开放(新增策略),对修改关闭(上下文不变)。

在 TypeScript 中,策略模式通过接口和多态实现,确保类型安全和代码清晰。

策略模式的结构

策略模式包含以下角色:

  1. Strategy(策略接口) :定义算法的公共接口,如 authenticate()
  2. ConcreteStrategy(具体策略) :实现策略接口,提供具体算法。
  3. Context(上下文) :维护策略对象的引用,通过接口调用算法。

优点

  • 解耦合:算法与上下文分离,降低耦合度。
  • 可扩展性:新增算法只需添加新策略类。
  • 类型安全:TypeScript 的类型系统确保接口一致性。

身份认证中的策略模式

在身份认证系统中(如 Passport.js),策略模式用于支持多种认证方式。例如:

  1. JWT认证:通过验证JSON Web Token来确认用户身份。
  2. Basic Auth:通过用户名和密码进行认证。
  3. OAuth:通过第三方服务(如Google、GitHub)进行认证。

以下以身份认证为例,展示策略模式如何支持动态选择认证方式,类似 Passport.js 的机制。

TypeScript 实现示例:身份认证中的策略模式

以下是一个身份认证系统的实现,动态选择认证策略(如JWT、Basic Auth)来验证用户请求。

typescript 复制代码
// 策略接口
interface AuthStrategy {
  authenticate(credentials: any): Promise<boolean>;
  getUserInfo(): string;
}

// 具体策略:JWT 认证
class JwtStrategy implements AuthStrategy {
  async authenticate(credentials: { token: string }): Promise<boolean> {
    // 模拟 JWT 验证逻辑
    if (credentials.token.startsWith("jwt_")) {
      return true; // 假设 token 以 "jwt_" 开头表示有效
    }
    throw new Error("无效的 JWT Token");
  }

  getUserInfo(): string {
    return "JWT 用户: user@example.com";
  }
}

// 具体策略:Basic Auth 认证
class BasicAuthStrategy implements AuthStrategy {
  async authenticate(credentials: { username: string; password: string }): Promise<boolean> {
    // 模拟 Basic Auth 验证逻辑
    if (credentials.username === "admin" && credentials.password === "pass123") {
      return true;
    }
    throw new Error("无效的用户名或密码");
  }

  getUserInfo(): string {
    return "Basic Auth 用户: admin";
  }
}

// 具体策略:OAuth 认证
class OAuthStrategy implements AuthStrategy {
  async authenticate(credentials: { accessToken: string }): Promise<boolean> {
    // 模拟 OAuth 验证逻辑
    if (credentials.accessToken.startsWith("oauth_")) {
      return true; // 假设 accessToken 以 "oauth_" 开头表示有效
    }
    throw new Error("无效的 OAuth Access Token");
  }

  getUserInfo(): string {
    return "OAuth 用户: oauth_user@example.com";
  }
}

// 上下文类:认证上下文
class AuthContext {
  private strategy: AuthStrategy;

  constructor(strategy: AuthStrategy) {
    this.strategy = strategy;
  }

  setStrategy(strategy: AuthStrategy): void {
    this.strategy = strategy;
  }

  async authenticate(credentials: any): Promise<string> {
    try {
      const isAuthenticated = await this.strategy.authenticate(credentials);
      if (isAuthenticated) {
        return this.strategy.getUserInfo();
      }
      return "认证失败";
    } catch (error) {
      return `认证错误: ${(error as Error).message}`;
    }
  }
}

// 客户端代码
async function main() {
  // 创建上下文并设置 JWT 策略
  let context = new AuthContext(new JwtStrategy());
  console.log(await context.authenticate({ token: "jwt_valid_token" })); // 输出: JWT 用户: user@example.com
  console.log(await context.authenticate({ token: "invalid_token" })); // 输出: 认证错误: 无效的 JWT Token

  // 切换到 Basic Auth 策略
  context.setStrategy(new BasicAuthStrategy());
  console.log(await context.authenticate({ username: "admin", password: "pass123" })); // 输出: Basic Auth 用户: admin
  console.log(await context.authenticate({ username: "admin", password: "wrong" })); // 输出: 认证错误: 无效的用户名或密码

  // 切换到 OAuth 策略
  context.setStrategy(new OAuthStrategy());
  console.log(await context.authenticate({ accessToken: "oauth_valid_token" })); // 输出: OAuth 用户: oauth_user@example.com
}

main();

运行结果

运行以上代码,将输出:

sql 复制代码
JWT 用户: user@example.com
认证错误: 无效的 JWT Token
Basic Auth 用户: admin
认证错误: 无效的用户名或密码
OAuth 用户: oauth_user@example.com

为什么使用策略模式?

在身份认证系统中(如 Passport.js),认证逻辑因方式不同而变化(如JWT解析、Basic Auth验证、OAuth回调)。使用策略模式:

  • 动态切换:无需修改认证上下文代码,只需注入新策略。
  • 扩展性:新增认证方式(如SAML、OpenID)只需实现新策略类。
  • 可测试性:每个策略独立,便于单元测试。

其他适用场景

虽然本示例聚焦身份认证,策略模式在认证系统中还可用于:

  • 令牌解析:不同类型的令牌(如JWT、API Key)使用不同解析逻辑。
  • 权限检查:根据用户角色或认证方式应用不同权限验证规则。
  • 日志记录:不同认证方式记录不同格式的日志。

总结

策略模式在身份认证系统中通过封装可互换的认证算法(如JWT、Basic Auth、OAuth),提供了动态选择和扩展机制。TypeScript 的类型系统确保策略接口的一致性,而认证上下文的示例展示了如何通过策略模式实现灵活的认证逻辑。这使得系统能够轻松适应多种认证需求,同时保持代码的可维护性和扩展性。

相关推荐
酷酷的逗逗乐1 分钟前
前端转 Agent 开发 · 第三节:LangChain 提示词模板
前端
Cache技术分享3 分钟前
516. Java 方法句柄 - 转换(进阶篇·下)
前端·后端
妙码生花3 分钟前
全网 8k star 的 BuildAdmin 正式发布 Golang 版本,这次我们在CRUD赛道杀死了比赛。
前端·后端·ai编程
Zane19944 分钟前
复制算法明明要浪费一半内存,为什么新生代还偏偏用它
java·后端
写代码像蔡徐抻5 分钟前
三年了,AI为何还没有抢走程序员饭碗?
前端·后端·面试
魔兽大山哥6 分钟前
【NL2SQL 实战 08】主链路:从提问到出数,图里跑了哪些节点
后端
Zane19947 分钟前
只重写了 __eq__,为什么类突然变得不可哈希了?常用魔法方法大盘点
后端·python
程序员cxuan8 分钟前
Claude Fable 5.1 的提示词又被扒了
人工智能·后端·程序员
梦曦i10 分钟前
unix-router v0.1.0 首发:uni-app x 的 vue-router 风格路由库
前端·uni-app
步行cgn11 分钟前
Spring Boot 绑定简单 Bean 详解
java·spring boot·后端