公共静态工厂方法

t0m*_*cat 20 java factory-pattern public-method

首先请原谅我,如果它是一个非常愚蠢的问题,我只是想学习这种语言的核心.我正在阅读Effective Java,第一章讨论静态工厂方法与构造函数.他们的利弊.很少有令我困惑的事情是:

  1. 静态工厂方法返回的对象的类是非公共的 - 这究竟是什么意思?
  2. 与构造函数不同,静态工厂方法不需要在每次调用时创建新对象 - 这是如何发生的?我只是为了获取一个新对象而调用工厂方法,我们是否在工厂方法中检查对象是否已经存在?

谢谢.

Mic*_*rdt 11

静态工厂方法返回的对象的类是非公共的 - 这究竟是什么意思?

这意味着静态工厂方法返回的对象的实际类可以是声明类型的子类,并且此子类不必是公共的.这只是客户端代码不应该关心的另一个实现细节.

与构造函数不同,静态工厂方法不需要在每次调用时创建新对象 - 这是如何发生的?我只是为了获取一个新对象而调用工厂方法,我们是否在工厂方法中检查对象是否已经存在?

是的,这是可以做到的一种方式.但实际上,一切皆有可能.


Ban*_*ane 5

首先,在Java点燃的情况下为您的选择提供了荣誉:Bloch的书是一本优秀的入门书。

要回答您的第二个问题(“与构造函数不同,在每次调用新工厂时不需要使用静态工厂方法来创建新对象”),重要的是要意识到Bloch在这里所说的是,对于静态工厂,您可以选择以下任一种:返回一个新对象或返回一个预先存在的对象。这完全取决于您要做什么。

例如,假设您有一个类型为Money的非常简单的值类。您的静态工厂方法可能应该返回一个新实例-即,一个具有特定Money值的新对象。因此,像这样:

public class Money { 

    private Money(String amount) { ... } /* Note the 'private'-constructor */

    public static Money newInstance(String amount) {
        return new Money(amount);
    }

}
Run Code Online (Sandbox Code Playgroud)

但是,假设您有一个管理某些资源的对象,并且想要通过一些ResourceManager类同步对该资源的访问。在这种情况下,您可能希望静态工厂方法将自身的相同实例返回给每个人-迫使每个人都要通过同一实例,以便该1个实例可以控制该过程。这遵循单例模式。像这样:

public ResourceManager {

    private final static ResourceManager me = new ResourceManager();

    private ResourceManager() { ... } /* Note the 'private'-constructor */

    public static ResourceManager getSingleton() {
        return ResourceManager.me;
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的方法强制您的用户只能使用一个实例,从而使您可以精确地控制谁(何时)有权访问您正在管理的内容。


要回答您的第一个问题,请考虑以下问题(当然,这不是最佳示例,这是特别的):

public class Money {

    private Money(String amount) { ... }


    public static Money getLocalizedMoney( MoneyType localizedMoneyType, String amount ) { 
        switch( localizedMoneyType ) {
            case MoneyType.US:
                return new Money_US( amount );
            case MoneyType.BR:
                return new Money_BR( amount );
            default:
                return new Money_US( amount );
        }
    }
}

public class Money_US extends Money { ... }

public class Money_BR extends Money { ... }
Run Code Online (Sandbox Code Playgroud)

请注意我现在该如何做:

Money money = Money.getLocalizedMoney( user_selected_money_type );
saveLocalizedMoney( money );
Run Code Online (Sandbox Code Playgroud)

同样,这是一个非常人为的示例,但希望它可以帮助您或多或少地了解Bloch在这一点上的想法。

其他答案很好-我只是认为,作为一个初学者,有时候查看一些实际代码会有所帮助。