m88体育 做Java有七、八年了,行业经典著作似乎一部都没有完整啃下来过,实在惭愧。就从名气最大的一部非入门级作品开始吧,Effective Java第二版。边读边记下一个脱水版,方便以后查阅。
静态工厂方法(static factory method)优于构造函数(constructor)
真是不习惯把这些术语翻译成中文,以后还是记原文好了。
static factory method代替构造函数的最简单例子:
Integer.valueOf(42)
Static factory method相对于constructor的好处:
1.有方法名,便于区分不同的方法
比如一个类
class MobilePhone { private boolean isSmart = false; private String os; public MobilePhone() { } public MobilePhone(String _os) { os = _os; isSmart = true; } }
这个类的两个constructor的区分,对使用者来说不是很清楚,经常需要看文档或代码才能明白。如果换成static factory method,就会好很多:
class MobilePhone { private boolean isSmart; private String os; private static final String NON_OS = "NON-OS"; private MobilePhone() { } public static MobilePhone createSmartPhone(String _os) { MobilePhone obj = new MobilePhone(); obj.os = _os; obj.isSmart = true; return obj; } public static MobilePhone createFeaturePhone() { MobilePhone obj = new MobilePhone(); obj.os = NON_OS; obj.isSmart = false; return obj; } }
2.不是必须创建新对象(object)
想法类似于Singleton的对象管理,可以控制对象的创建数量,增进性能。需要注意,这种应用中类通常被要求是不可变的(immutable)
很简单的例子就是Boolean类的创建方法:
public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE :Boolean.FALSE; }
用这一方法取得的Boolean对象,在内存中永远只有两个:Boolean.TRUE和Boolean.FALSE。极端一些的用法,把构造函数完全禁用,保证了相互equal()对象的唯一性之后,可以用==代替equals()来验证对象是否相等。
3.可以返回任何子类的对象
把接口作为static factory的返回类型,实际可以返回这一接口的任意实现。典型应用就是JDBC API:
public interface DataSource extends CommonDataSource,Wrapper { Connection getConnection() throws SQLException; Connection getConnection(String username, String password) throws SQLException; }
取决于所配置的jdbcDriver类型,两个getConnection()方法可以返回各种各样的jdbc连接:Oracle、MySQL、Postgre...
4.对泛型(generic types)对象的创建,减少代码复杂度
Map<String, List<String>> m = new HashMap<String, List<String>>();
可以被简化为:
Map<String, List<String>> m = HashMap.newInstance();
坏处:
1.只提供static factory method的类,如果没有公共或受保护constructor,无法继承
2.不容易和其他静态方法作区分
尽量使用约定俗成的方法名:valueOf、of、getInstance、newInstance等等
结论是,static factory method完胜,在任何需要提供公共constructor的场合,都应更优先考虑static factory method。