1

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.

5
  • Is the only code changing always the type of AutomataGraph created for each concrete factories? Where the arguments (args) comes from? Are they hard-coded, are they always the same? Commented Jul 8, 2014 at 1:35
  • Actually there's no arguments passed; that was a mistake. The only thing changing is the type. Commented Jul 8, 2014 at 1:40
  • It seems your factory is also too much. It should only know how to instanciate an AutomataGraph, the rest shouldn't be of it's concern. Another object could be responsible for genAllUnlabeledGraphs and rely on an injected factory to create AutomataGraph instances. Commented Jul 8, 2014 at 1:41
  • @plalx: I guess this was just bad naming conventions, the OPs AutomataGraphBuilder does not seem to have the purpose to build AutomataGraphs. Commented Jul 8, 2014 at 1:49
  • Would you be able to suggest an alternative? Commented Jul 8, 2014 at 1:52

1 Answer 1

1

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(…);
Sign up to request clarification or add additional context in comments.

4 Comments

I like this answer. Does this have parallels to java/c++.
Seems to be a wrong/unecessary use of inheritance. The factory is just doing too much. Another object should be responsible for genAllUnlabeledGraphs and a factory should be injected into it to make sure it does instanciate the correct class. The design would be much simpler, no?
Perhaps I'm not trying to make a factory class in the textbook sense so I should have changed the title. I just want a class to handle the creation and manipulation of sets of objects. This is what I had assumed a factory class was for: the manipulation/creation of objects.
@plalx: If you have an inheritance setup (which the class names in question suggested), this seems reasonable to me. Sure, a method (possibly partially applied) that just takes the factory as a second parameter would be the other solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.