在 Java 中,获得一个类实例最简单的方法就是使用 new 关键字,通过构造函数来实现对象的创建。
eg:
Dog dog=new Dog();
Date date=new Date();
而静态工厂方法:
Calendar calendar = Calendar.getInstance();
Integer number = Integer.valueOf("3");
像这样,不通过new关键字,通过一个静态方法得到类的实列的方法就是静态工厂方法。
就是直接可以通过静态方法来实例化一个对象
public class Car{
public static Car newtInstance(){
return new Car();
}
}
Car .newtInstance();
创建 Car对象直接调用Car类的静态方法newtInstance方法来进行实现
就是先创建类对象,然后通过对象来调用创建实例对象的方法
public class CarFactory {
public Car newtInstance(){
return new Car();
}
}
CarFactory carFactory =new CarFactory();
carFactory.newtInstance();
静态工厂方法通常指的是某个类里的静态方法,通过调用该静态方法可以得到属于该类的一个实例;
工厂模式是一种设计模式。具体看设计模式。
如果要说相似的话,静态工厂方法跟简单工厂模式倒有那么点像,不过区别也挺大,简单工厂模式里的静态工厂方法会创建各种不同的对象(不同类的实例),而静态工厂方法一般只创建属于该类的一个实例(包括子类);
由于语言的特性,Java 的构造函数都是跟类名一样的。这导致的一个问题是构造函数的名称不够灵活,经常不能准确地描述返回值,在有多个重载的构造函数时尤甚,如果参数类型、数目又比较相似的话,那更是很容易出错。
eg:
Date date2 = new Date("0");
Date date3 = new Date(1,2,1);
Date 类有很多重载函数,我们发现,可读性差,不查文档,不看注释很难知道其创建的对象的具体含义
JDK中的Boolean类的valueOf方法可以很好的印证这个优势,在Boolean类中,有两个事先创建好的Boolean对象(True,False)
public final class Boolean implements java.io.Serializable,
Comparable
{
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code true}.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code false}.
*/
public static final Boolean FALSE = new Boolean(false);
当我们调用Boolean.valueOf(“true”)方法时,返回的就是这两个实例的引用,这样可以避免创建不必要的对象,如果使用构造器的话,就达不到这种效果了;
public static Boolean valueOf(String s) {
return toBoolean(s) ? TRUE : FALSE;
}
Class Person {
public static Person getInstance(){
return new Person();
// 这里可以改为 return new Player() / Cooker()
}
}
Class Player extends Person{
}
Class Cooker extends Person{
}
public static Person getPlayer(){
return new Player ();//或者return new Cooker();
}
这条主要是针对带泛型类的繁琐声明而说的,需要重复书写两次泛型参数:
class MyMap {
/**
*
*/
public MyMap()
{
}
public static MyMap newInstance(){
return new MyMap();
}
}
MyMap map1 = new MyMap();
//更加简洁,不需要重复指明类型参数,可以自行推导出来
MyMap map2 = MyMap.newInstance();
不过自从 java7 开始,这种方式已经被优化过了 —— 对于一个已知类型的变量进行赋值时,由于泛型参数是可以被推导出,所以可以在创建实例时省略掉泛型参数。
Map map = new HashMap<>();
如下类,不能被其它类继承
class MyMap {
private MyMap()
{
}
public static MyMap newInstance(){
return new MyMap();
}
}
所以,一般一个静态工厂方法需要有详细的注释,遵守标准的命名,如使用getInstance、valueOf、newInstance等方法名;
下面是一些静态工厂方法的常用名称。以下清单并非完整:
总之,静态工厂方法和公共构造方法都有它们的用途,并且了解它们的相对优点是值得的。通常,静态工厂更可取,因此避免在没有考虑静态工厂的情况下提供公共构造方法。
本文是根据Effctive java和网上部分博客总结而出。 侵删。