首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为工厂方法使用私有构造函数?

为工厂方法使用私有构造函数?
EN

Stack Overflow用户
提问于 2014-05-03 07:42:20
回答 2查看 6.5K关注 0票数 3

假设我正在构建一个不可变的Yahtzee记分卡类:

代码语言:javascript
复制
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);
    }

}

基本上,我不想暴露类的内部结构。如果我没有私有构造函数,那么我就需要使用一个带有Map参数的公共构造函数,就像私有构造函数一样(而且我可能也会失去withScore()方法),以便允许评分。但是,这是一种有效的工厂方法吗?

EN

回答 2

Stack Overflow用户

发布于 2014-05-03 07:50:00

一个非常常见且很好的模式是拥有所有私有构造函数和公共静态工厂方法:

代码语言:javascript
复制
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;
    }
}

注意:这允许不同的工厂方法具有相同的参数类型,这是构造函数所不允许的。

票数 5
EN

Stack Overflow用户

发布于 2014-05-03 07:50:49

工厂方法旨在允许您在不指定确切类型的情况下获取对象。

例如,来自Effective Java,第2版:

类java.util.EnumSet (项目32),在版本1.5中引入,没有公共构造函数,只有静态工厂。它们根据基础枚举类型的大小返回两个实现之一:如果它有64个或更少的元素,就像大多数枚举类型一样,静态工厂返回一个由单个RegularEnumSet支持的RegularEnumSet实例;如果该枚举类型有65个或更多元素,则工厂返回一个由长数组支持的JumboEnumSet实例。

这两个实现类的存在对客户端是不可见的。如果RegularEnumSet不再为小型枚举类型提供性能优势,则可以从未来的版本中消除它,而不会产生任何不良影响。类似地,未来的版本可能会添加第三或第四个EnumSet实现,如果它被证明对性能有益的话。客户端既不知道也不关心它们从工厂返回的对象的类;它们只关心它是EnumSet的某个子类。

使用构造函数而不是您建议的静态方法打破了工厂方法模式,因为通过直接使用构造函数可以指定一个实现。

在您的示例中,如果您想使用工厂方法,则应将默认构造函数设为私有,这样客户端就不能直接实例化ScoreCard。此时,您可以在工厂方法中自由使用ScoreCard的任何特定实现。例如,如果您创建了由TreeMap支持的第二个ScoreCard类,您可以通过更改静态工厂来切换客户端获得的ScoreCard实现。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23438566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档