面试题答案
一键面试优化思路
- 分析现有类继承结构:找出哪些功能在复用和维护上存在困难,确定这些功能相关的类及其关系。
- 提取可复用功能:将那些难以复用和维护的功能从原有的类继承体系中提取出来,封装成独立的模块或对象。
- 引入组合模式:在需要使用这些功能的类中,通过组合的方式将提取出来的功能对象包含进来,而不是通过继承获取功能。
关键TypeScript代码示例
假设我们有一个 Animal
类作为基类,Dog
和 Cat
类继承自它,并且 Dog
和 Cat
都有叫声相关的功能,但这个功能复用和维护出现困难。
// 提取可复用功能,比如叫声功能
class Sound {
makeSound(): string {
return 'Some sound';
}
}
// 原有的Animal类
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}
// Dog类,通过组合方式使用Sound功能
class Dog extends Animal {
sound: Sound;
constructor(name: string) {
super(name);
this.sound = new Sound();
}
bark() {
return this.sound.makeSound();
}
}
// Cat类,同样通过组合方式使用Sound功能
class Cat extends Animal {
sound: Sound;
constructor(name: string) {
super(name);
this.sound = new Sound();
}
meow() {
return this.sound.makeSound();
}
}
提升说明
- 代码可读性:组合模式将功能封装成独立的模块,使得每个类的职责更加清晰。例如上述代码中,
Sound
类专注于叫声功能,Dog
和Cat
类只需要关注自身特定行为以及如何组合使用Sound
功能,代码结构更易理解。 - 可维护性:当
Sound
功能需要修改时,只需要在Sound
类中进行修改,而不需要担心影响到继承体系中的多个子类。如果是继承方式,可能需要在多个子类中重复修改相同功能代码,增加出错风险。 - 扩展性:如果有新的叫声需求,可以很方便地创建新的
Sound
子类或修改Sound
类,而不影响Dog
和Cat
类的其他逻辑。同时,如果有新的动物类需要类似叫声功能,也可以轻松组合Sound
对象来实现,不需要复杂的继承关系调整。