Javascript:如何在不创建循环依赖关系的情况下重用创建子实例的方法

时间:2018-09-09 21:20:52

标签: javascript node.js typescript

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 { }

如何在不创建循环依赖关系的情况下对其进行重组,以便:

  1. 每个类都在单独的文件中
  2. addChild()方法适用于所有子级,而无需重复执行代码

我已经读到,对于基类而言,了解子类通常是一个糟糕的模式,但是我不确定哪种模式更好。

Example that might make more sense

编辑:已删除type作为参数

2 个答案:

答案 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 Listclass ListFactoryclass 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 { }