什么是“静态工厂”方法?
当前回答
我想我会在这篇文章中添加一些我所知道的东西。我们在最近的android项目中广泛使用了这种技术。除了使用new操作符创建对象,您还可以使用静态方法来实例化一个类。代码清单:
//instantiating a class using constructor
Vinoth vin = new Vinoth();
//instantiating the class using static method
Class Vinoth{
private Vinoth(){
}
// factory method to instantiate the class
public static Vinoth getInstance(){
if(someCondition)
return new Vinoth();
}
}
静态方法支持有条件的对象创建:每次调用构造函数都会创建一个对象,但您可能不希望这样。假设你想检查一些条件,然后你想创建一个新对象。除非满足条件,否则不会每次都创建一个新的Vinoth实例。
另一个例子来自Effective Java。
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
此方法将布尔原语值转换为布尔对象引用。boolean . valueof (boolean)方法说明了我们,它从不创建对象。静态工厂方法从重复调用中返回相同对象的能力允许类在任何时候对存在的实例保持严格控制。
与构造函数不同的是,静态工厂方法可以返回返回类型的任何子类型的对象。这种灵活性的一个应用是API可以返回对象,而不需要将它们的类设为公共。以这种方式隐藏实现类可以得到一个非常紧凑的API。
Calendar.getInstance()是一个很好的例子,它根据地区创建一个佛教日历,日本帝国日历或默认的格鲁吉亚日历。
另一个例子,我认为是单例模式,你使你的构造函数私有创建一个自己的getInstance方法,你确保,总是有一个实例可用。
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}
其他回答
静态工厂方法模式是封装对象创建的一种方式。如果没有工厂方法,只需直接调用类的构造函数:Foo x = new Foo()。使用这种模式,你可以调用工厂方法:Foo x = Foo.create()。构造函数被标记为private,因此只能从类内部调用它们,而工厂方法被标记为静态,因此可以在没有对象的情况下调用它。
这种模式有几个优点。一个是工厂可以从许多子类(或接口的实现者)中选择并返回。通过这种方式,调用者可以通过参数指定所需的行为,而不必知道或理解潜在的复杂类层次结构。
Another advantage is, as Matthew and James have pointed out, controlling access to a limited resource such as connections. This a way to implement pools of reusable objects - instead of building, using, and tearing down an object, if the construction and destruction are expensive processes it might make more sense to build them once and recycle them. The factory method can return an existing, unused instantiated object if it has one, or construct one if the object count is below some lower threshold, or throw an exception or return null if it's above the upper threshold.
根据维基百科上的文章,多个工厂方法还允许对相似的参数类型进行不同的解释。通常构造函数与类具有相同的名称,这意味着具有给定签名的构造函数只能有一个。工厂没有那么多限制,这意味着你可以有两个不同的方法接受相同的参数类型:
Coordinate c = Coordinate.createFromCartesian(double x, double y)
and
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Rasmus指出,这也可以用来提高可读性。
One of the advantages of the static factory methods with private constructor(object creation must have been restricted for external classes to ensure instances are not created externally) is that you can create instance-controlled classes. And instance-controlled classes guarantee that no two equal distinct instances exist(a.equals(b) if and only if a==b) during your program is running that means you can check equality of objects with == operator instead of equals method, according to Effective java.
The ability of static factory methods to return the same object from repeated invocations allows classes to maintain strict control over what instances exist at any time. Classes that do this are said to be instance-controlled. There are several reasons to write instance-controlled classes. Instance control allows a class to guarantee that it is a singleton (Item 3) or noninstantiable (Item 4). Also, it allows an immutable class (Item 15) to make the guarantee that no two equal instances exist: a.equals(b) if and only if a==b. If a class makes this guarantee, then its clients can use the == operator instead of the equals(Object) method, which may result in improved performance. Enum types (Item 30) provide this guarantee.
摘自Effective Java, Joshua Bloch(第1项,第6页)
静态
用关键字'static'声明的成员。
工厂方法
方法,用于创建和返回新对象。
在Java中
编程语言与“静态”的含义相关,但与“工厂”的定义无关。
静态工厂的优点之一是API可以返回对象,而不需要将它们的类设为public。这导致了非常紧凑的API。在java中,这是通过Collections类实现的,它隐藏了大约32个类,这使得它的集合API非常紧凑。
当您希望确保只有一个实例将返回要使用的具体类时,静态工厂方法很好。
例如,在一个数据库连接类中,您可能希望只有一个类创建数据库连接,因此如果您决定从Mysql切换到Oracle,您只需更改一个类中的逻辑,而应用程序的其余部分将使用新的连接。
如果您希望实现数据库池,那么也可以在不影响应用程序其余部分的情况下完成。
它保护应用程序的其余部分不受您可能对工厂所做的更改的影响,这就是目的。
它是静态的原因是,如果你想跟踪一些有限的资源(套接字连接或文件句柄的数量),那么这个类可以跟踪已经传递和返回了多少,这样你就不会耗尽有限的资源。
推荐文章
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- Maven依赖Servlet 3.0 API?
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表
- Spring JPA选择特定的列
- URLEncoder不能翻译空格字符
- Java中的super()
- 如何转换JSON字符串映射<字符串,字符串>与杰克逊JSON