JS/TS如何重构多子类组合逻辑 保留方法命名与原有功能
方案实现:使用类工厂Mixin模式
该方案无需修改现有所有类的定义、完全保留原有方法命名与功能,也不需要手动维护N*M数量的组合类,同时支持方法内访问this、修改实例属性的需求。
基础JS实现
// 你现有代码完全保留无需修改 class Animal { constructor(nickname){ this.nickname = nickname } fullSoundSentence(){ return `${this.nickname} ${this.composesound()}!` } } class Dog extends Animal { doessound(){ return "barks" } } class Cat extends Animal { doessound(){ return "meows" } } class LoudAnimal extends Animal { composesound(){ return `loudly ${this.doessound()}` } } class CalmAnimal extends Animal { composesound(){ return `calmly ${this.doessound()}` } } // 新增通用组合函数,动态生成任意组合类 function combineAnimalAndMode(AnimalClass, ModeClass) { class CombinedAnimal extends ModeClass { constructor(nickname) { super(nickname) // 合并动物类的所有原型方法 Object.getOwnPropertyNames(AnimalClass.prototype).forEach(method => { if (method !== 'constructor' && !this[method]) { this[method] = AnimalClass.prototype[method] } }) } } return CombinedAnimal }
使用示例
// 按需动态生成组合类,新增动物或模式时无需额外维护组合代码 const CalmDog = combineAnimalAndMode(Dog, CalmAnimal) const LoudCat = combineAnimalAndMode(Cat, LoudAnimal) // 调用逻辑和原生类完全一致 const myCalmDog = new CalmDog("阿黄") console.log(myCalmDog.fullSoundSentence()) // 输出:阿黄 calmly barks! const myLoudCat = new LoudCat("咪咪") console.log(myLoudCat.fullSoundSentence()) // 输出:咪咪 loudly meows!
TypeScript版本(带类型约束)
abstract class Animal { constructor(public nickname: string) {} fullSoundSentence() { return `${this.nickname} ${this.composesound()}!` } protected abstract composesound(): string } class Dog extends Animal { doessound(){ return "barks" } } class Cat extends Animal { doessound(){ return "meows" } } class LoudAnimal extends Animal { composesound(){ return `loudly ${this.doessound()}` } } class CalmAnimal extends Animal { composesound(){ return `calmly ${this.doessound()}` } } // 类型约束定义 interface IAnimal extends Animal { doessound(): string } type ModeConstructor = new (nickname: string) => Animal type AnimalConstructor = new (nickname: string) => IAnimal function combineAnimalAndMode<T extends AnimalConstructor, M extends ModeConstructor>( AnimalClass: T, ModeClass: M ): new (nickname: string) => InstanceType<T> & InstanceType<M> { class CombinedAnimal extends ModeClass { constructor(nickname: string) { super(nickname) Object.getOwnPropertyNames(AnimalClass.prototype).forEach(method => { if (method !== 'constructor' && !(method in this)) { (this as any)[method] = AnimalClass.prototype[method] } }) } } return CombinedAnimal as any }
TS版本下组合后的实例会自动继承两个类的所有类型定义,无需额外声明类型。
内容的提问来源于stack exchange,提问作者Franartur Čech
相关产品推荐
相关产品推荐

