我们何时以及如何使用构造函数
Foo bar = new Foo();
我们何时以及如何使用getInstance()(静态工厂方法)
Foo bar = Foo.getInstance();
这两者有什么区别,我总是使用第一种方式,但何时使用第二种方式?
答案 0 :(得分:90)
每个人似乎都专注于单身,而我认为问题实际上是关于构造函数与静态工厂方法。
这实际上是项目1:考虑Joshua Bloch的Effective Java的静态工厂方法而不是构造函数:
第1项:考虑静态工厂方法而不是构造函数
类允许的常规方法 客户端获取自己的实例 是提供一个公共构造函数。 应该有另一种技术 成为每个程序员的一部分 工具包。一堂课可以提供公共 静态工厂方法,它只是一个返回的静态方法 班级的实例。这是一个简单的 来自
Boolean
的例子(盒装 原始类型的基本类boolean
)。这种方法翻译了一个 布尔原始值转换为Boolean
对象引用:public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
请注意,静态工厂方法是 与工厂方法不同 来自设计模式的模式 [Gamma95,p。 107]。静电厂 此项目中描述的方法没有 在设计中直接等效 图案
一个类可以为其客户提供 静态工厂方法代替,或 除了,建设者。 提供静态工厂方法 而不是公共构造函数 优点和缺点。
优点(引用本书):
缺点(仍引用该书):
答案 1 :(得分:8)
您有两个问题:我应该何时调用 getInstance()
方法,何时创建一个?
如果您决定是否致电 getInstance()
方法,则很容易。您只需阅读课程文档,了解何时应该调用它。例如,NumberFormat
提供构造函数和 getInstance()
方法; getInstance()
方法会为您提供本地化的NumberFormat
。另一方面,对于Calendar
,构造函数受到保护。您有致电getInstance()
以获得一个。
如果您决定是否创建 getInstance()
方法,则需要确定您要完成的工作。您不要求人们调用您的构造函数(您创建singleton或factory),或者您不介意(如{{1}上面,他们为了方便调用者而初始化一些对象。)
长话短说?不要担心在自己的代码中创建NumberFormat
方法。如果它们有用的时候出现,你就会知道。通常,如果可以调用类的构造函数,那么即使该类提供getInstance()
方法,您也可能应该这样做。
答案 2 :(得分:7)
getInstance方法的用途:
但是大部分时间你的对象都是简单的POJO,公共构造函数的使用是最实际和最明显的解决方案。
U1:来自其他类的getInstance
要返回其他类的实例:
public class FooFactory {
public static Foo getInstance() {
return new Foo();
}
}
NumberFormat.getInstance
方法执行此操作,因为它们实际返回DecimalFormat
的实例。
U2:单身人士问题
单例模式限制了面向对象编程的许多好处。单身人士通常拥有私人建筑师,因此你无法扩展他们。由于您将通过其getInstance方法访问它而不引用任何接口,因此您将无法将其交换为其他实现。
答案 3 :(得分:6)
如果您可以同时使用它们,那么它听起来就像是一个执行不力的singleton pattern。
如果您打算在系统中只有一个类的单个实例,那么请使用第二个选项,然后将构造函数设为私有。
使用第一个允许构建该类的多个对象。
但不要给你的班级两种可能性。
注意不要过度使用单身人士,只有在系统中只存在一个实例时才使用它们,否则你将限制在其他项目中重复使用你的课程的可能性。能够从项目中的任何地方调用getInstance听起来很有趣但是不清楚谁实际拥有该实例:nobody和/或all。如果你在项目中有很多单身人士,你可以打赌系统设计很差(通常)。单身人士应谨慎使用,同样的建议也适用于全局变量。
答案 4 :(得分:1)
我总是喜欢静态工厂而非常规构造函数的一种情况是当我知道对象构造会变慢时。我在构造函数上做了简单的初始化,但是如果我需要创建一些重的东西,我将使用静态方法并记录行为。
答案 5 :(得分:0)
单身人士是邪恶的。我所看到的围绕它的问题不是关于系统的重复使用或可扩展性(虽然我可以看到它会如何发生),更多的是我无法计算我在一个系统中看到模糊错误的次数由单身人士组成的制度。
如果您确实需要使用单件,请确保其范围极窄,即明智地限制系统中了解其的其他对象的数量。