用静态工厂方法代替构造器
本节提到的静态工厂方法区别于设计模式的工厂方法,而是于构造器平行的一个概念。静态工厂方法与构造器各有优缺点,使用时要根据实际场景做出判断。
静态工厂方法或构造器的使用场景:在类中,客户端获取它自身的一个实例。
静态工厂方法(SFM):返回一个类的实例的静态方法。
建议使用SFM的场景:
第一:使用的构造器参数名称不明确说明返回对象。本条使用于业务场景中有必须要避免的返回值。
eg:构造器BigInteger(i,i,R)返回值可能为素数,若业务代码中对于返回值有高频的检查素数场景,为了避免生产事故,建议使用自定义名为BigInteger.probablePrime的静态工厂方法,增加代码的可维护性。
第二:不必每次调用时创建一个新对象。
这使得不可变类可以使用预先构建好的实例,或者将构建好的实例缓存起来,进行重复利用,从而避免了创建不必要的重复对象。
Boolean.valueOf(boolean b)方法说明了这项技术,它从来不创建对象。
第三:可以返回原返回类型的任何子类型的对象。灵活,就是自定义。利用Java的多态的特性,使得工厂可以产生基类的同时注入子类实现。
实例代码摘自网络:
public interface Food {
/**
* 使得所有食物都有一个共有的introduce方法
*/
public void introduce();
}
/**
* 定义食物的子类:鱼
*/
public class Fish implements Food{
@Override
public void introduce() {
System.out.println("i am a fish");
}
}
/**
* 食物的子类,水果
*/
public class Fruit implements Food {
@Override
public void introduce() {
System.out.println("i am the fruit");
}
}
/**
* 通过反射机制实现的工厂
*/
public class FoodFactory {
public static Food getFood(String type) {
Food food = null;
try {
food = (Food) Class.forName("info.zhw." + type).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return food;
}
}
第四:方法返回对象所属的类,在编写包含该静态工厂方法的类时可以不存在。例如JDBC API,多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦处理。
/** 返回Connection,该类为DriverManager.class */
@CallerSensitive
public static Connection getConnection(String url,
java.util.Properties prop) throws SQLException {
return (getConnection(url, info, Reflection.getCallerClass()));
}