Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using private constructors for factory methods?

Let's say I'm building an immutable Yahtzee scorecard class:

public final class Scorecard {

    private Map<Category, Integer> scorecard = new HashMap<Category, Integer>();

    public Scorecard() {
        // Instantiates a new empty scorecard
    }

    private Scorecard(Map<Category, Integer> scorecard) {
        this.scorecard = scorecard;
    }

    public Scorecard withScore(Category category, int[] roll) {
        newScorecard = new HashMap<Category, Integer>(scorecard); // Pretend that this is a deep-copy
        newScorecard.put(category, calculateScoreFromRoll(roll));
        return new Scorecard(newScorecard);
    }

    public int getScore(Category category) {
        return scorecard.get(category);
    }

}

Basically I don't want to expose the internals of the class. If I didn't have a private constructor then I would need to use a public constructor with a Map argument just like the private one (and I could essentialy lose the withScore() method too) in order to allow scoring. But is this a valid way of doing factory methods?

like image 200
soren.qvist Avatar asked Mar 12 '26 09:03

soren.qvist


1 Answers

A very common, and good pattern is to have all private constructors and public static factory methods:

public class MyClass {
    private MyClass() {}
    public static MyClass fromA(A foo) {
        MyClass o = new MyClass();
        o.field = bar; // etc
        return o;
    }
    public static MyClass fromB(B foo) {
        MyClass o = new MyClass();
        o.field = bar; // etc
        return o;
    }
}

Note: This allows different factory methods with the same parameter types, which constructors do not allow.

like image 107
Bohemian Avatar answered Mar 13 '26 23:03

Bohemian