该知识点是自己从书籍中学习的笔记。
静态工厂方法
定义:类提供一个静态方法,来返回该类的实例。代替使用公有构造方法的方式来获取类的实例。
例子:
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
优点:
1. 类的构造方法的名字必须要和类名字一样,但是静态工厂方法可以有单独的名字。
1).如果一个构造方法的参数并不能够描述出返回的对象时,这时使用静态工厂方法可以使一个类更容易使用和方便与他人阅读。例如:虽然BigInteger(int, int, Random),可以构造一个素数对象,但是使用BigInteger.probablePrime()这种方法更容易阅读。
2).如果一个类的构造方法只是其参数类型不同的话,就会使开发人在阅读代码需要借助于帮助文档才能够知道构造的对象的意义。因此在这种情况下,可以使用静态工厂方法来构造对象,因为每个静态工厂方法都必须有独立的签名(签名,我理解为方法名字)。
2. 使用静态工厂方法可以不必要求每次都生成新的对象。
1).例如Boolean.valueOf(boolean) 该方法并不是每次都创建新的对象,在源码可以看到
“public static BigInteger valueOf(long l)
{
if(l == 0L)
return ZERO;
if(l > 0L && l <= 16L)
return posConst[(int)l];
if(l < 0L && l >= -16L)
return negConst[(int)(-l)];
else
return new BigInteger(l);
}”
上面代码说明BigInteger缓存了常用的对象实例,和Flyweight的设计模式相似。
2).使用静态工厂方法可以确保多次调用构造实例时,返回的实例对象是一样的,相当于是单例。
3. 使用静态工厂方法可以返回一个原返回类型的子类型的对象。
1) 使用该方式可以不必将class都声明成public的。比如说java.util.Collections这个类中就有很多的静态类。
2)JDBC的实现方式。
“Connection充当的是Service Interface,DriverManager.registerDriver充当注册角色,DriverManager.getConnection充当获取Service Access API,Driver充当接口”。注册是将厂商提供的lib加载进来,然后就可以链接数据库了。
4. 降低了建立参数化类型的实例的冗长。例如:“
Map<String, String> map = new HashMap<String, String>();”你可以先写一个继承HashMap的类,在该类中编写getInstance()的静态工厂方法:“
public static <K, V> java.util.HashMap<K, V> getInstance() {
return new java.util.HashMap<K, V>();
}”,然后使用以下的方法:“
Map<String, String> map = HashMap.getInstance();”来创建HashMap对象。
缺点:
1.一个类没有public、protected或者默认的构造方法的话,那么该class就不能够被子类化。就是说如果一个的构造方法是private的话,那么该类就没有子类。
2. 很难将静态工厂方法和类中的其他静态方法区别出来。Java的版本文档没有做特别的标注这两种方法的区别。
使用静态工厂方法的命名习惯
1. valueOf()--返回一个已经存在的实例。笼统的说,该方法的参数值和返回的对象值是一样的,比如说枚举的valueOf()方法。
2. of()--valueOf()方法的简写。
3. getInstance()--返回一个参数描述的对象,返回的对象不一定和参数值一样。如果没有参数的话,通常是返回单例。
4. newIntance()--通常是返回不同的一个对象的值。
5. getType()--通常是静态工厂方法使用的不同子类对象。
6. newType()--通常是静态工厂方法使用的不同子类对象。