Java 何时使用构造函数,何时使用 getInstance() 方法(静态工厂方法)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3169372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use a Constructor and when to use getInstance() method (static factory methods)?
提问by zengr
When and how should we use a constructor
Foo bar = new Foo();
And when and how should we use getInstance() (static factory methods)
Foo bar = Foo.getInstance();
我们应该何时以及如何使用构造函数
Foo bar = new Foo();
我们应该何时以及如何使用 getInstance()(静态工厂方法)
Foo bar = Foo.getInstance();
What is the difference between these two? I have always used a constructor, but when should I use getInstance()
instead?
这两者有什么区别?我一直使用构造函数,但我应该什么时候使用getInstance()
呢?
采纳答案by Pascal Thivent
Everybody seems to focus on singletons while I think that the question is actually about constructor vs static factory methods.
每个人似乎都关注单例,而我认为问题实际上是关于构造函数与静态工厂方法。
This is actually Item 1: Consider static factory methods instead of constructorsof Effective Javaby Joshua Bloch:
这实际上是第1项:考虑静态工厂方法而不是构造函数的 有效的Java由约书亚·布洛克:
Item 1: Consider static factory methods instead of constructors
The normal way for a class to allow a client to obtain an instance of itself is to provide a public constructor. There is another technique that should be a part of every programmer's toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class. Here's a simple example from
Boolean
(the boxed primitive class for the primitive typeboolean
). This method translates a boolean primitive value into aBoolean
object reference:public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
Note that a static factory method is not the same as the Factory Methodpattern from Design Patterns[Gamma95, p. 107]. The static factory method described in this item has no direct equivalent in Design Patterns.
A class can provide its clients with static factory methods instead of, or in addition to, constructors. Providing a static factory method instead of a public constructor has both advantages and disadvantages.
第 1 条:考虑静态工厂方法而不是构造函数
一个类允许客户端获取自身实例的正常方式是提供一个公共构造函数。还有另一种技术应该成为每个程序员工具包的一部分。一个类可以提供一个公共 静态工厂方法,它只是一个返回类实例的静态方法。这是来自
Boolean
(原始类型的装箱原始类boolean
)的一个简单示例。此方法将布尔原始值转换为Boolean
对象引用:public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
请注意,静态工厂方法 与设计模式中的工厂方法模式不同[Gamma95,p。107]。此项中描述的静态工厂方法在设计模式中没有直接等效项。
一个类可以为它的客户提供静态工厂方法来代替构造函数,或者除了构造函数之外。提供静态工厂方法而不是公共构造函数既有优点也有缺点。
Advantages (quoting the book):
优点(引用本书):
- One advantage of static factory methods is that, unlike constructors, they have names.
- A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they're invoked.
- A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
- A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances.
- 静态工厂方法的优点之一是,与构造函数不同,它们有名称。
- 静态工厂方法的第二个优点是,与构造函数不同,它们不需要在每次调用时都创建一个新对象。
- 静态工厂方法的第三个优点是,与构造函数不同,它们可以返回其返回类型的任何子类型的对象。
- 静态工厂方法的第四个优点是它们减少了创建参数化类型实例的冗长。
Disadvantages (still quoting the book):
缺点(还是引用书上的):
- The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.
- A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.
- 只提供静态工厂方法的主要缺点是没有公共或受保护构造函数的类不能被子类化。
- 静态工厂方法的第二个缺点是它们不容易与其他静态方法区分开来。
回答by jdehaan
If you can use both then it sound like a poorly implemented singleton pattern.
如果您可以同时使用两者,那么这听起来像是一个实现不佳的单例模式。
Use the second option if you intend to have only one single instance of the class in your system and make the constructor private then.
如果您打算在您的系统中只有该类的一个实例,然后将构造函数设为私有,请使用第二个选项。
Use the first to allow building several objects of the class.
使用第一个允许构建类的多个对象。
BUT do not give your class the both possibilities.
但是不要给你的班级两种可能性。
Take care not to over-use singletons, only use them if really only one instance shall exist in the system otherwise you would limit the possibilities of re-use of your class in other projects. It sounds interesting to be able to call getInstance from everywhere in your project but that makes unclear who actually owns that instance: nobody and/or all. If you have a lot of singletons in a project you can bet that the system is poorly designed (usually). Singletons should be used with care, the same advice than for global variables apply.
注意不要过度使用单例,只有在系统中真的只有一个实例时才使用它们,否则你会限制在其他项目中重用你的类的可能性。能够从项目中的任何地方调用 getInstance 听起来很有趣,但这并不清楚谁真正拥有该实例:没有人和/或所有人。如果你在一个项目中有很多单身人士,你可以打赌这个系统设计得很差(通常)。应谨慎使用单例,与适用于全局变量的建议相同。
回答by Chris B.
You've got two questions: when should I calla getInstance()
method, and when should I createone?
你有两个问题:什么时候应该调用一个getInstance()
方法,什么时候应该创建一个方法?
If you're deciding whether to calla getInstance()
method, it's easy. You just need to read the class documentation to find out when you should call it. For example, NumberFormat
provides a constructor anda getInstance()
method; the getInstance()
method will give you a localized NumberFormat
. For Calendar
, on the other hand, the constructor is protected. You haveto call getInstance()
to get one.
如果您正在决定是否调用一个getInstance()
方法,这很容易。您只需要阅读类文档以了解何时应该调用它。例如,NumberFormat
提供一个构造函数和一个getInstance()
方法;该getInstance()
方法将为您提供本地化的NumberFormat
. 对于Calendar
,另一方面,构造函数是受保护的。你必须打电话getInstance()
才能得到一个。
If you're deciding whether to createa getInstance()
method, you need to decide what you're trying to accomplish. Either you don'twant people to call your constructor (you're creating a singletonor a factory), or you don't mind (as in NumberFormat
above, where they're initializing some objects for the convenience of the caller).
如果您正在决定是否创建一个getInstance()
方法,您需要决定您要完成什么。要么您不希望人们调用您的构造函数(您正在创建单例或工厂),要么您不介意(如上NumberFormat
所示,他们正在初始化一些对象以方便调用者)。
Long story short?Don't worry about creating getInstance()
methods in your own code. If the time arises when they'll be useful, you'll know. And in general, if you cancall a class's constructor, you're probably supposed to be doing that, even if the class provides a getInstance()
method.
长话短说?不要担心getInstance()
在您自己的代码中创建方法。如果到时候它们会派上用场,你就会知道。通常,如果您可以调用类的构造函数,那么您可能应该这样做,即使该类提供了getInstance()
方法。
回答by krock
The uses for getInstance methods:
getInstance 方法的用途:
- If you want to control/restrict construction e.g. Singleton
- implement Factory pattern, e.g. DriverManager.getConnection
- When you want to provide better name as to how the instance is constructed (constructors must have the same name as the class name), checkout the NumberFormatfactory methods getCurrencyInstance, getIntegerInstanceand others as examples of this.
- 如果您想控制/限制构造,例如Singleton
- 实现工厂模式,例如DriverManager.getConnection
- 如果您想提供关于实例构造方式的更好名称(构造函数必须与类名具有相同的名称),请查看NumberFormat工厂方法getCurrencyInstance、getIntegerInstance和其他方法作为示例。
But most of the time your object will be a simple POJOand usage of public constructors is most practical and obvious solution.
但大多数情况下,您的对象将是一个简单的POJO,并且使用公共构造函数是最实用和最明显的解决方案。
U1: getInstance From Another Class
U1:从另一个类中获取实例
To return an instance of a different class:
返回不同类的实例:
public class FooFactory {
public static Foo getInstance() {
return new Foo();
}
}
NumberFormat.getInstance
methods do this as they actually return instances of DecimalFormat
.
NumberFormat.getInstance
方法这样做是因为它们实际上返回DecimalFormat
.
U2: Singleton Problems
U2:单例问题
The singleton pattern restricts many of the benefits of object oriented programming. Singletons generally have private constructors, therefore you cannot extend them. As you will be accessing it via its getInstance method and not referencing any interface, you will not be able to swap it out for another implementation.
单例模式限制了面向对象编程的许多好处。单例通常具有私有构造函数,因此您不能扩展它们。由于您将通过其 getInstance 方法访问它而不引用任何接口,因此您将无法将其替换为另一个实现。
回答by rupjones
Singletons are evil. The problems I've seen surrounding it are not about re-use or extendability of a system (although I could see how that could occur), more so that I can't count the number of times i've seen obscure bugs in a system that arise from singletons.
单身人士是邪恶的。我所看到的围绕它的问题不是关于系统的重用或可扩展性(尽管我可以看到它是如何发生的),更多的是我无法计算我在一个系统中看到模糊错误的次数由单身人士产生的系统。
If you do need to use a singleton, ensure it's scope is extremely narrow, i.e. judiciously limit the number of other objects in your system that know about it.
如果您确实需要使用单例,请确保它的范围非常狭窄,即明智地限制系统中了解它的其他对象的数量。
回答by Guu
One case in which I always prefer a static factory over a regular constructor is when I know the object construction will be slowish. I do simple initialization on constructor, but if I need to create something heavy I'll use a static method and document the behavior.
我总是喜欢静态工厂而不是常规构造函数的一种情况是,当我知道对象构造会很慢时。我对构造函数进行了简单的初始化,但是如果我需要创建一些繁重的东西,我将使用静态方法并记录行为。