abstract class Fruit {
private content: Fruit[] = [];
addChild() {
// Pick one at random (using this as an example instead of the actual criteria that determines this)
const type = pickOne(['apple', 'banana', 'cherry']);
switch (type) {
case 'apple':
this.content.push(new Apple());
case 'banana':
this.content.push(new Banana());
case 'cherry':
this.content.push(new Cherry());
}
}
}
class Apple extends Fruit { }
class Banana extends Fruit { }
class Cherry extends Fruit { }
如何在不创建循环依赖关系的情况下对其进行重组,以便:
addChild()
方法适用于所有子级,而无需重复执行代码我已经读到,对于基类而言,了解子类通常是一个糟糕的模式,但是我不确定哪种模式更好。
Example that might make more sense
编辑:已删除type
作为参数
答案 0 :(得分:4)
您需要将抽象类与工厂类分开(创建新实例):
// fruit.ts
abstract class Fruit {
private content: Array<Fruit> = [];
addChild(child: Fruit) {
this.content.push(child);
}
}
// fruit-factory.ts
class FruitFactory {
create(type: 'apple' | 'banana' | 'cherry'): Fruit {
switch (type) {
case 'apple':
return new Apple();
case 'banana':
return new Banana();
case 'cherry':
return new Cherry();
}
}
}
// apple.ts
class Apple extends Fruit { }
// banana.ts
class Banana extends Fruit { }
// cherry.ts
class Cherry extends Fruit { }
Factory design pattern对于隔离和重用创建对象的代码很有用。
在您更详细的示例中,loadChildren
不必绑定到List
抽象类。这使得List
抽象具有3个职责:作为列表,从外部源加载数据和创建新实体。
single responsibility principle是可维护代码的指导原则,其中每个类都有一个职责。
我建议您根据确定的职责将List
对象分为3类:abstract class List
,class ListFactory
和class DataFetcher
。
这将使您可以为每个此类定义一个良好的接口。
答案 1 :(得分:0)
您可以简单地传递构造函数而不是字符串:
abstract class Fruit {
private content: Fruit[] = [];
addChild<F extends Fruit>(C: new (...args: any) => F) {
this.content.push(new C());
}
}
class Apple extends Fruit { }
class Banana extends Fruit { }
class Cherry extends Fruit { }