MST

星途 面试题库

面试题:TypeScript类继承链与多态性在大型项目架构中的优化策略

假设你正在参与一个大型前端项目,项目中使用TypeScript构建了复杂的类继承体系来实现多态性。随着项目规模的增长,继承链变得冗长且维护困难,同时多态性的实现导致部分代码性能下降。请阐述你会采取哪些优化策略来改善这种情况,包括但不限于如何重构继承链、优化多态性实现方式以及对设计模式的应用,结合具体的TypeScript代码示例说明。
40.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

1. 重构继承链

1.1 提取公共部分为混合类(Mixin)

继承链冗长可能是因为多个子类重复继承了一些通用功能。可以将这些通用功能提取出来,通过混合类的方式复用。

// 定义一个通用功能的混合类
type Constructor<T = {}> = new (...args: any[]) => T;
function Loggable<TBase extends Constructor>(Base: TBase) {
    return class extends Base {
        log(message: string) {
            console.log(`${this.constructor.name}: ${message}`);
        }
    };
}

class Animal {
    constructor(public name: string) {}
}

// 使用混合类扩展Animal类
class Dog extends Loggable(Animal) {
    bark() {
        this.log('Woof!');
    }
}

const dog = new Dog('Buddy');
dog.bark(); // 输出: Dog: Woof!

1.2 组合代替继承

过多的继承可以通过组合的方式简化。例如,如果一个类继承了多个父类的功能,可以将这些功能作为成员变量引入。

class Flyable {
    fly() {
        console.log('I can fly');
    }
}

class Swimmable {
    swim() {
        console.log('I can swim');
    }
}

class Duck {
    private flyable: Flyable;
    private swimmable: Swimmable;

    constructor() {
        this.flyable = new Flyable();
        this.swimmable = new Swimmable();
    }

    performActions() {
        this.flyable.fly();
        this.swimmable.swim();
    }
}

const duck = new Duck();
duck.performActions(); 
// 输出: 
// I can fly
// I can swim

2. 优化多态性实现方式

2.1 使用函数重载优化多态

在一些情况下,函数重载可以提供更清晰和高效的多态实现。

function printValue(value: string): void;
function printValue(value: number): void;
function printValue(value: any) {
    if (typeof value ==='string') {
        console.log(`String: ${value}`);
    } else if (typeof value === 'number') {
        console.log(`Number: ${value}`);
    }
}

printValue('Hello'); // 输出: String: Hello
printValue(42); // 输出: Number: 42

2.2 基于类型判断的多态

利用TypeScript的类型断言和类型保护进行更灵活的多态。

class Shape {
    draw() {
        console.log('Drawing a shape');
    }
}

class Circle extends Shape {
    draw() {
        console.log('Drawing a circle');
    }
}

class Square extends Shape {
    draw() {
        console.log('Drawing a square');
    }
}

function drawShapes(shapes: Shape[]) {
    shapes.forEach(shape => {
        if (shape instanceof Circle) {
            shape.draw();
        } else if (shape instanceof Square) {
            shape.draw();
        } else {
            shape.draw();
        }
    });
}

const shapes: Shape[] = [new Circle(), new Square()];
drawShapes(shapes); 
// 输出: 
// Drawing a circle
// Drawing a square

3. 设计模式的应用

3.1 策略模式

当多态性导致性能问题时,策略模式可以将不同的行为封装成独立的策略类。

interface SortStrategy {
    sort(arr: number[]): number[];
}

class QuickSortStrategy implements SortStrategy {
    sort(arr: number[]): number[] {
        if (arr.length <= 1) {
            return arr;
        }
        const pivot = arr[Math.floor(arr.length / 2)];
        const left = [];
        const right = [];
        const equal = [];
        for (const num of arr) {
            if (num < pivot) {
                left.push(num);
            } else if (num > pivot) {
                right.push(num);
            } else {
                equal.push(num);
            }
        }
        return [...this.sort(left), ...equal, ...this.sort(right)];
    }
}

class MergeSortStrategy implements SortStrategy {
    sort(arr: number[]): number[] {
        if (arr.length <= 1) {
            return arr;
        }
        const mid = Math.floor(arr.length / 2);
        const left = arr.slice(0, mid);
        const right = arr.slice(mid);
        return this.merge(this.sort(left), this.sort(right));
    }

    merge(left: number[], right: number[]): number[] {
        let result: number[] = [];
        let i = 0;
        let j = 0;
        while (i < left.length && j < right.length) {
            if (left[i] < right[j]) {
                result.push(left[i]);
                i++;
            } else {
                result.push(right[j]);
                j++;
            }
        }
        return result.concat(left.slice(i)).concat(right.slice(j));
    }
}

class Sorter {
    private strategy: SortStrategy;

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

    setStrategy(strategy: SortStrategy) {
        this.strategy = strategy;
    }

    sortArray(arr: number[]): number[] {
        return this.strategy.sort(arr);
    }
}

const sorter = new Sorter(new QuickSortStrategy());
const numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
console.log(sorter.sortArray(numbers)); 
// 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

sorter.setStrategy(new MergeSortStrategy());
console.log(sorter.sortArray(numbers)); 
// 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

3.2 装饰器模式

用于在运行时给对象添加新的功能,而不是通过继承来扩展类。

// 定义一个装饰器函数
function Logger(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (...args: any[]) {
        console.log(`Calling ${propertyKey} with args:`, args);
        const result = originalMethod.apply(this, args);
        console.log(`${propertyKey} returned:`, result);
        return result;
    };
    return descriptor;
}

class MathOperations {
    @Logger
    add(a: number, b: number) {
        return a + b;
    }
}

const mathOps = new MathOperations();
mathOps.add(2, 3); 
// 输出: 
// Calling add with args: [2, 3]
// add returned: 5