You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

我是否正确实现了代理模式?附TypeScript代码求技术指点

关于你的AuthService设计与代码改进建议

核心疑问澄清

你的当前设计不是代理模式的典型实现。代理模式的核心是控制对真实服务对象的访问,比如添加权限校验、延迟加载、日志记录、远程调用等额外逻辑;而你的AuthService只是单纯转发所有方法调用到传入的真实服务,没有任何额外控制或增强逻辑,更偏向于依赖注入的服务包装器,或者说空实现的装饰器模式。这种设计本身不算反模式,但如果只是单纯转发,其实可以简化,不需要额外包装类,直接依赖AuthInterface接口即可。

代码改进点

1. 完善类型注解与访问控制

AuthService中的SomeService缺少类型注解,且应该用private readonly修饰,避免外部修改或误访问:

class AuthService<ServiceType, UserType> implements AuthInterface<ServiceType, UserType> {
  private readonly authService: AuthInterface<ServiceType, UserType>;
  constructor(authService: AuthInterface<ServiceType, UserType>) {
    this.authService = authService;
  }
  // ... 方法实现
}

2. 保持接口与实现的参数一致性

接口中定义的参数是可选的(带?),但你的实现类把参数改成了必填,这会导致类型不匹配。应该保持一致性:

// 接口定义
interface AuthInterface<ServiceType, UserType> {
  init(initCallback?: () => ServiceType): ServiceType;
  signIn(authProvider?: ServiceType, signIncallback?: (authProvider?: ServiceType) => boolean | Error): boolean;
  getID(authProvider?: ServiceType, getIDCallback?: (authProvider?: ServiceType) => UserType): UserType;
}

// 实现类保持可选参数
class AuthService<ServiceType, UserType> implements AuthInterface<ServiceType, UserType> {
  // ...
  init(initCallback?: () => ServiceType): ServiceType {
    return this.authService.init(initCallback);
  }
  // ...
}

3. 让泛型具备实际意义

当前泛型ServiceType和UserType没有绑定具体业务类型,导致泛型失去作用。以Firebase为例,应该明确指定类型:

// 导入Firebase类型(需安装@firebase/auth类型包)
import { Auth, User } from "firebase/auth";

// 针对Firebase的实现
class FirebaseAuth implements AuthInterface<Auth, User> {
  private authInstance?: Auth;

  init(initCallback?: () => Auth): Auth {
    this.authInstance = initCallback ? initCallback() : /* 这里可以写默认的Firebase初始化逻辑 */;
    return this.authInstance;
  }

  signIn(authProvider?: Auth): boolean {
    if (!authProvider) throw new Error("Auth provider not initialized");
    // 实际调用Firebase登录逻辑
    try {
      // 比如 auth.signInWithEmailAndPassword(...)
      return true;
    } catch (e) {
      throw new Error("Sign in failed");
    }
  }

  getID(authProvider?: Auth): User {
    if (!authProvider || !authProvider.currentUser) throw new Error("User not authenticated");
    return authProvider.currentUser;
  }
}

4. 移除回调耦合,让服务实现自身逻辑

当前设计把业务逻辑放在外部回调中,导致AuthInterface与业务代码耦合,违背了单一职责原则。应该让具体服务类(比如FirebaseAuth)自身实现认证逻辑,而不是依赖外部回调。

5. 优化错误处理

避免使用never类型,改用明确的Error抛出,让类型更清晰,也便于调用方捕获错误。

6. 简化不必要的包装

如果你的AuthService只是单纯转发调用,其实可以直接依赖AuthInterface接口,不需要额外的包装类。比如在业务代码中直接注入具体的服务实例:

// 业务代码中直接使用
const firebaseAuth = new FirebaseAuth();
// 直接调用firebaseAuth的方法,不需要通过AuthService包装
firebaseAuth.init();

改进后的完整代码示例

import { Auth, User } from "firebase/auth";

interface AuthInterface<ServiceType, UserType> {
  init(initCallback?: () => ServiceType): ServiceType;
  signIn(authProvider?: ServiceType): boolean;
  getID(authProvider?: ServiceType): UserType;
}

class FirebaseAuth implements AuthInterface<Auth, User> {
  private authInstance?: Auth;

  init(initCallback?: () => Auth): Auth {
    this.authInstance = initCallback ? initCallback() : /* 此处添加Firebase默认初始化逻辑 */;
    if (!this.authInstance) throw new Error("Failed to initialize Firebase Auth");
    return this.authInstance;
  }

  signIn(authProvider?: Auth): boolean {
    const targetAuth = authProvider || this.authInstance;
    if (!targetAuth) throw new Error("Auth provider not initialized");
    
    // 模拟Firebase登录逻辑
    try {
      // 实际代码:await targetAuth.signInWithEmailAndPassword(email, password);
      return true;
    } catch (error) {
      throw new Error(`Sign in failed: ${(error as Error).message}`);
    }
  }

  getID(authProvider?: Auth): User {
    const targetAuth = authProvider || this.authInstance;
    if (!targetAuth) throw new Error("Auth provider not initialized");
    
    const user = targetAuth.currentUser;
    if (!user) throw new Error("No authenticated user found");
    return user;
  }
}

// 业务代码使用示例
const authService = new FirebaseAuth();
const firebaseAuthInstance = authService.init();
authService.signIn(firebaseAuthInstance);
const currentUser = authService.getID();

内容的提问来源于stack exchange,提问作者ElMoscaviador

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 21:20:19