user3015797
user3015797

Reputation: 887

Implementing Inheritance In Factory Classes Without Copying Code In Javascript

This question includes some math concepts but they're irrelevant to the meat of the question.

I'm implementing an API for studying automata on graphs. I have an abstract class called AutomataGraph which is inherited by the different types of AutomataGraph's I'm interested in. Each type has different rules for how it progresses through its states. For each type I have a builder/factory class inheriting from AutomataGraphBuilder for doing different interesting things with the graphs/automata. One such thing is generating all of the unlabeled graphs with n nodes. In the AutomaGraphBuilder class this method looks like:

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

This works fine except when I want to extend this call to the JohnConwayAutomataGraphBuilder I have to copy all of the code just to change the "graph = new AutomataGraph()" line to "graph = new JohnConwayAutomataGraph()".

Any suggestions? I'm more interested in looking for some general structural insights and not the fact that this is javascript.

EDIT: The pseudocode is of course fairly different from the actual algorithm and just there to demonstrate that there's excessive code copying.

Upvotes: 1

Views: 55

Answers (1)

Bergi
Bergi

Reputation: 664650

Basically you'd have a link from the builder class the item class, by the means of a functionality that allows you to create new instances of it (in js, that's just the constructor).

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

Then JohnConwayAutomataGraphBuilder would just be a subclass that overwrites the .itemConstructor property (or some unrelated class which just shares the method and has a .itemConstructor property pointing somewhere else).


The other way would be the use of closures, dynamically creating the generate methods:

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(…);

Upvotes: 1

Related Questions