首先,如果我的问题太蠢,请原谅我。我只是想全面学习这门语言。我正在阅读《Effective Java》,第一章讲述了静态工厂方法与构造函数之间的优缺点。有几件事情让我感到困惑:
- 由静态工厂方法返回的对象的类是非公共的——这具体是什么意思?
- 与构造函数不同,调用静态工厂方法时不需要每次创建一个新对象——这是如何发生的?我只是调用工厂方法来获取一个新对象,难道在工厂方法中要检查对象是否已经存在吗?
谢谢。
首先,如果我的问题太蠢,请原谅我。我只是想全面学习这门语言。我正在阅读《Effective Java》,第一章讲述了静态工厂方法与构造函数之间的优缺点。有几件事情让我感到困惑:
谢谢。
静态工厂方法返回的对象类是非公开的——这究竟意味着什么?
这意味着,由静态工厂方法返回的对象的实际类可以是声明类型的子类,并且该子类不必是公共的。这只是另一个客户端代码不需要关心的实现细节。
与构造函数不同,调用静态工厂方法时不要求每次都创建一个新对象——这是如何实现的?我只是为了获取新对象而调用工厂方法,我们在工厂方法中添加检查以检查对象是否已存在吗?
是的,这是其中一种实现方式。但实际上,任何事情都有可能发生。
new
就没有这个选项。 - ColinDpublic class Money {
private Money(String amount) { ... } /* Note the 'private'-constructor */
public static Money newInstance(String amount) {
return new Money(amount);
}
}
但是假设您有一些管理某些资源的对象,并且您想通过一些ResourceManager类同步访问该资源。在这种情况下,您可能希望您的静态工厂方法向每个人返回相同的自身实例--强制每个人都通过同一实例,以便该1个实例可以控制进程。这遵循单例模式。像这样:
public ResourceManager {
private final static ResourceManager me = new ResourceManager();
private ResourceManager() { ... } /* Note the 'private'-constructor */
public static ResourceManager getSingleton() {
return ResourceManager.me;
}
}
上述方法可以强制用户只能使用单个实例,从而让您精确控制谁可以(何时)访问您管理的内容。
回答你的第一个问题,请考虑以下内容(尽管这并不是最好的示例,它相当临时):
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 { ... }
Money money = Money.getLocalizedMoney( user_selected_money_type );
saveLocalizedMoney( money );
再次强调,这只是一个非常牵强的例子,但希望它能帮助你更加理解Bloch所说的那一点。
其他答案都很好,但我认为作为初学者,有时看到一些实际的代码会有所帮助。
getLocalizedMoneyType(DefaultMoneyTypeBasedOnLocale, amount)
--因为没有人已经执行了new Money(amount)
,所以不会破坏任何现有的客户端代码。 - Banefirst-example
的情况下,我们使用静态工厂方法是因为我们想在未来使用其他类型和改进,对吗? - Shennew
关键字时,作为开发人员,你知道JDK会创建该对象的新实例。作者所说的是,当您使用静态方法时,开发人员不再知道该方法是否正在创建一个新实例或可能执行其他操作。其他操作可能包括重用缓存数据、对象池、创建私有实现并返回类的子类。new SomeType(int, int, String, int)
而不是 new SomeType(int, int, int, String)
...”) - Mark Peters通过查看使用静态工厂方法这两个属性的代码,可以回答你的两个问题。我建议查看Guava的ImmutableList。
注意无参数工厂方法of()
总是返回相同的实例(它不会每次创建新实例)。如果仔细观察,您还会注意到其copyOf(Iterable)
工厂方法实际上返回传递给它的对象,如果该对象本身就是ImmutableList
。这两者都利用了ImmutableList
永远不会改变的事实。
请注意,它中的各种工厂方法返回不同的子类,例如EmptyImmutableList
、SingletonImmutableList
和RegularImmutableList
,而不会暴露这些对象的类型。方法签名只显示它们返回ImmutableList
,并且所有ImmutableList
的子类都具有包私有(默认)可见性,使它们对库用户不可见。这为多个实现类带来了所有优点,而从用户的角度来看,没有增加任何复杂性,因为他们只允许将ImmutableList
视为单个类型。
除了ImmutableList
之外,Guava中的大多数可实例化类都使用静态工厂方法。Guava还展示了《Effective Java》中提出的许多原则(这并不奇怪,因为它是根据这些原则设计的,并在Josh Bloch的指导下进行了设计),因此在阅读本书时,您可能会发现它更有用。