做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。

提交评论


安全码
刷新