MST
星途 面试题库

面试题:TypeScript参数装饰器与依赖注入结合实现复杂业务逻辑解耦

设计一个场景,在一个大型前端项目中,某个方法需要依赖多个外部服务,使用TypeScript参数装饰器结合依赖注入的方式,实现对这些依赖的解耦与管理。要求详细阐述设计思路,并编写核心代码片段,同时说明这种方式在项目维护和扩展方面的好处。
36.0万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 依赖注入概念:依赖注入是一种设计模式,通过将依赖(外部服务)传递给需要它们的组件(方法),而不是让组件自己创建或查找依赖,从而实现解耦。
  2. TypeScript参数装饰器:用于在方法参数上添加元数据,在我们的场景中,可以用来标记哪些参数是外部服务依赖。
  3. 依赖管理容器:创建一个容器来存储和管理所有的外部服务实例,在运行时,根据参数装饰器标记,从容器中获取对应的依赖注入到方法中。

核心代码片段

// 依赖管理容器
const serviceContainer: { [key: string]: any } = {};

// 参数装饰器,用于标记依赖
function inject(serviceKey: string) {
    return function (target: any, propertyKey: string, parameterIndex: number) {
        if (!Reflect.hasMetadata('design:paramtypes', target, propertyKey)) {
            Reflect.defineMetadata('design:paramtypes', [], target, propertyKey);
        }
        const existingTypes = Reflect.getMetadata('design:paramtypes', target, propertyKey);
        existingTypes[parameterIndex] = { serviceKey };
        Reflect.defineMetadata('design:paramtypes', existingTypes, target, propertyKey);
    };
}

// 模拟外部服务
class ExternalService1 {
    public doSomething1() {
        return 'Service1 doing something';
    }
}
class ExternalService2 {
    public doSomething2() {
        return 'Service2 doing something';
    }
}

// 注册服务到容器
serviceContainer['ExternalService1'] = new ExternalService1();
serviceContainer['ExternalService2'] = new ExternalService2();

// 使用依赖注入的类和方法
class MyClass {
    public myMethod(@inject('ExternalService1') service1: ExternalService1, @inject('ExternalService2') service2: ExternalService2) {
        return `${service1.doSomething1()} and ${service2.doSomething2()}`;
    }
}

// 获取实例并调用方法
const myClassInstance = new MyClass();
const result = myClassInstance.myMethod();
console.log(result);

在项目维护和扩展方面的好处

  1. 维护方面
    • 代码可读性增强:通过参数装饰器和依赖注入,明确了方法对外部服务的依赖关系,使得代码阅读者能快速了解方法所需的外部资源。
    • 易于修改:如果某个外部服务的实现发生变化,只需要在服务的具体实现类中修改,而不需要在每个依赖该服务的方法中修改,因为依赖是通过容器注入的,方法本身不关心具体的创建过程。
  2. 扩展方面
    • 添加新服务容易:要引入新的外部服务,只需要在容器中注册该服务,并在需要的方法参数上使用装饰器标记,不需要对现有代码结构进行大规模改动。
    • 测试方便:在单元测试中,可以轻松地替换真实的外部服务为模拟服务,通过注入模拟对象,方便对方法进行独立测试,提高测试的准确性和可靠性。