【问题标题】:Implementing Inheritance In Factory Classes Without Copying Code In Javascript在工厂类中实现继承而不在 Javascript 中复制代码
【发布时间】:2014-07-08 01:27:28
【问题描述】:

这个问题包含一些数学概念,但它们与问题的实质无关。

我正在实现一个用于研究图形自动机的 API。我有一个名为 AutomataGraph 的抽象类,它由我感兴趣的不同类型的 AutomataGraph 继承。每种类型对于它如何通过其状态进行处理都有不同的规则。对于每种类型,我都有一个从 AutomataGraphBuilder 继承的构建器/工厂类,用于使用图形/自动机做不同的有趣事情。其中一件事是生成所有具有 n 个节点的未标记图。在 AutomaGraphBuilder 类中,此方法如下所示:

AutomataGraphBuilder.prototype.genAllUnlabeledGraphs = function(n){
    var graphs = [];
    var graph;

    for(all possible graphs){
        graph = new AutomataGraph();
        if (should add graph) {
            graphs.push(graph);
        }
    }

    return graphs;
}

这很好用,除非我想将此调用扩展到 JohnConwayAutomataGraphBuilder,我必须复制所有代码才能将“graph = new AutomataGraph()”行更改为“graph = new JohnConwayAutomataGraph()”。

有什么建议吗?我更感兴趣的是寻找一些一般的结构见解,而不是这是 javascript。

编辑:伪代码当然与实际算法有很大不同,只是为了证明存在过多的代码复制。

【问题讨论】:

  • 唯一的代码是否总是改变为每个具体工厂创建的AutomataGraph 的类型?论点 (args) 来自哪里?它们是硬编码的吗?它们总是一样的吗?
  • 实际上没有传递任何参数;那是个错误。唯一改变的是类型。
  • 看来你的工厂也太多了。它应该只知道如何实例化AutomataGraph,其余的不应该是它的关注点。另一个对象可能负责 genAllUnlabeledGraphs 并依赖注入的工厂来创建 AutomataGraph 实例。
  • @plalx:我想这只是糟糕的命名约定,OP AutomataGraphBuilder 似乎没有构建AutomataGraphs的目的。
  • 您能提出替代方案吗?

标签: javascript oop inheritance structure factory


【解决方案1】:

基本上,您可以通过允许您创建它的新实例的功能(在 js 中,这只是构造函数),从构建器类获得项目类的链接。

AutomataGraphBuilder.prototype.itemConstructor = AutomataGraph;
AutomataGraphBuilder.prototype.genAllUnlabeledGraphs = function(n) {
    var constructor = this.itemConstructor;
    var graphs = [];

    for(all possible graphs){
        var graph = new constructor(args);
        if (should add graph) {
            graphs.push(graph);
        }
    }
    return graphs;
}

那么JohnConwayAutomataGraphBuilder 将只是一个覆盖.itemConstructor 属性的子类(或一些不相关的类,它只共享该方法并且具有指向其他地方的.itemConstructor 属性)。


另一种方法是使用闭包,动态创建 generate 方法:

function makeGraphGenerator(constructor) {
    return function(n) {
        var graphs = [];

        for(all possible graphs){
            var graph = new constructor(args);
            if (should add graph) {
                graphs.push(graph);
            }
        }
        return graphs;
    };
}

AutomataGraphBuilder.prototype.genAllUnlabeledGraphs = makeGraphGenerator(AutomataGraph);
JohnConwayAutomataGraphBuilder.prototype.… = makeGraphGenerator(…);

【讨论】:

  • 我喜欢这个答案。这是否与 java/c++ 有相似之处。
  • 似乎是对继承的错误/不必要的使用。工厂做的太多了。另一个对象应该负责genAllUnlabeledGraphs,并且应该将一个工厂注入其中以确保它确实实例化了正确的类。设计会简单得多,不是吗?
  • 也许我并不想在教科书的意义上创建一个工厂类,所以我应该更改标题。我只想要一个类来处理对象集的创建和操作。这就是我假设工厂类的用途:操作/创建对象。
  • @plalx:如果你有一个继承设置(有问题的类名建议),这对我来说似乎是合理的。当然,将工厂作为第二个参数的方法(可能部分应用)将是另一种解决方案。
猜你喜欢
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多