MST

星途 面试题库

面试题:TypeScript装饰器在大型项目中的设计与优化

在一个复杂的企业级前端项目中,使用了大量的TypeScript装饰器来处理业务逻辑。随着项目的发展,装饰器之间的依赖关系变得复杂,导致代码维护困难。请提出一种合理的架构设计方案,来优化装饰器之间的依赖关系,提高代码的可维护性和可扩展性。并结合TypeScript的语言特性,阐述如何在实际代码中实现这一方案。
21.5万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

架构设计方案

  1. 模块化与分层
    • 将装饰器按照功能进行模块化划分,例如,与权限相关的装饰器放在一个模块,与日志记录相关的装饰器放在另一个模块。
    • 对业务逻辑进行分层,比如分为数据层、业务逻辑层、表示层等。装饰器在不同层中各司其职,减少跨层依赖。
  2. 依赖注入
    • 通过依赖注入的方式管理装饰器之间的依赖关系。创建一个容器来管理依赖对象,在需要使用装饰器的地方,从容器中获取依赖对象,而不是在装饰器内部直接实例化依赖。
  3. 使用接口和抽象类
    • 定义接口来规范装饰器的行为,这样不同的装饰器实现类可以按照统一的接口标准进行开发。同时,通过抽象类来提取装饰器之间的公共逻辑,减少重复代码。

实际代码实现

  1. 模块化实现
    • 创建权限装饰器模块 permissionDecorator.ts
// permissionDecorator.ts
export function requirePermission(permission: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // 权限检查逻辑
            console.log(`Checking permission: ${permission}`);
            return originalMethod.apply(this, args);
        };
        return descriptor;
    };
}
- **创建日志记录装饰器模块 `loggingDecorator.ts`**:
// loggingDecorator.ts
export function logMethod() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            console.log(`Calling method ${propertyKey}`);
            const result = originalMethod.apply(this, args);
            console.log(`Method ${propertyKey} returned: ${result}`);
            return result;
        };
        return descriptor;
    };
}
  1. 依赖注入实现
    • 创建依赖注入容器 diContainer.ts
// diContainer.ts
class DIContainer {
    private dependencies: { [key: string]: any } = {};
    register(key: string, value: any) {
        this.dependencies[key] = value;
    }
    resolve(key: string) {
        return this.dependencies[key];
    }
}
const container = new DIContainer();
export default container;
- **在装饰器中使用依赖注入**:
// someService.ts
import container from './diContainer';
export function someDecorator() {
    const dependency = container.resolve('someDependency');
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            // 使用依赖进行逻辑处理
            console.log(`Using dependency: ${dependency}`);
            return originalMethod.apply(this, args);
        };
        return descriptor;
    };
}
  1. 接口和抽象类实现
    • 定义装饰器接口 DecoratorInterface.ts
// DecoratorInterface.ts
export interface DecoratorInterface {
    (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
}
- **创建抽象装饰器类 `AbstractDecorator.ts`**:
// AbstractDecorator.ts
import { DecoratorInterface } from './DecoratorInterface';
export abstract class AbstractDecorator implements DecoratorInterface {
    constructor() {}
    abstract (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
    protected commonLogic() {
        console.log('This is common logic in abstract decorator');
    }
}
- **具体装饰器类继承抽象装饰器类**:
// anotherDecorator.ts
import { AbstractDecorator } from './AbstractDecorator';
export class AnotherDecorator extends AbstractDecorator {
    constructor() {
        super();
    }
    public (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor {
        this.commonLogic();
        const originalMethod = descriptor.value;
        descriptor.value = function (...args: any[]) {
            console.log('Another decorator logic');
            return originalMethod.apply(this, args);
        };
        return descriptor;
    }
}