第一条:考虑用静态工厂代替构造器
对于类而言,为了让使用者获取它自身的一个实例,最常见的方法就是提供一个公有的构造器。但是有一种方法,他就是静态工厂方法(static factory method),它只返回类的实例的静态方法。比如说我们所有的基本类型的封装类中的valueOf()方法
1 public static Boolean valueOf(boolean b){ 2 3 return b ? Boolean.TRUE : Boolean.FALSE; 4 5 }
类可以通过静态的工厂方法提供它的客户端,而不是通过构造器。提供静态工厂方法而不是公用的构造器,这样做有几大优势:
1、静态工厂方法与构造器的不同的第一大优势在于,它们都有名称
这一点很明显,我们的构造器函数名称只能是与类名相同,但是它具体做了什么,则不能够通过类名反应出来。在这方面静态工厂方法更具优势。
2、静态工厂方法与构造器的不同的第二大优势在于,它不必每次调用的时候都创建一个新对象。
用构造方法创建实例时,就意味着你每次都是new一个新的对象,而静态工厂方法则可以将我们事先创建好的对象以单例的形式返回给客户端。
3、静态工厂方法与构造器的不同的第三大优势在于,它们可以返回原返回类型的任何子类类型的对象。
构造函数永远都不会有返回值,而我们的静态工厂方法它就是一个普通的静态方法,我们子类中完全可以返回任何超类中返回对象的子类类型。这也加强了类创建 的灵活性。
4、静态工厂方法与构造器的不同的第三大优势在于,在创建参数化类型实例的时候,它们是代码变得更加简洁。
如下代码所示:
Map<String, List<String>> map = new HashMap<String, List<String>>();
这样的创建方式,最麻烦的莫过于声明和创建都要重复泛型(即<String, List<String>>).
如果我们的类中有这样的方法:
public static<K, V> HashMap<K, V> newInstance(){ return new HashMap<K, V>(); }
我们直选要在变量声明的时候,确定泛型即可:
Map<String, List<String>> m = HashMap.newInstance()
当然静态工厂方法也是具有缺点的:
1、类如果不含有公有的或者受保护的构造器,就不能够被子类化
我们在实现静态工厂方法的时候,为了屏蔽掉构造创建对象,就会将该类的所有构造函数私有化,但是一旦我们的类的构造器私有化之后,它就不能够被继承。
因而我们一般都是在工具类或者是最终类当中使用这种对象创建模式。
2、它们本质上与其他的静态方法没有区别
为了到达区分效果,我们只能通过确定名称的统一才能够达到。
如:
valueOf()
of()
getInstance()
newInstance()
getType()
newType()