《Effective Java》的第一章节就介绍了,利用静态工厂的方法来替代构造器。静态工厂方法是返回类实例的一种静态方法。下面是一个经典例子:
public static Boolean valueOf (boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
上面的这个静态方法是将boolean 类型的值转换成了一个Boolean 类型的引用。
用静态工厂方法替代公有的构造器有几点优势:
1.静态工厂方法可以设置每个实例自己的名称。这就意味着代码更加易读,所代表的更具体更有意义。
2.静态工厂方法在调用的时候可以不创建新的对象 可以用事先创建好的实例,当然也是可以返回新的实例。更加的灵活。用缓存好的实例会大大降低创建实例的开销成本。就如上面valueOf 方法,返回的一直都是相同的对象而没有返回新的实例。
3.静态工厂方法可以返回原类型的任何子类型的对象 为了更好的理解《Effective Java》 举了一个例子:`
//Service 接口
public interface Service {
void print();
}
定义一个用于生成Service 实例的一个接口
// Provider 接口
public interface Provider {
/**
* @return 返回Service 实例
*/
Service newService();
}
非实例化的类 Service 进行注册和访问
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Services implements Service {
// 禁止外部实例化
private Services() {
}
/*
* Map service names to services
* */
private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
private static final String DEFAULT_PROVIDER_NAME = "DefaultName";
//Provider 注册的方法
public static void registerDefaultProvider(Provider provider) {
registerProvider(DEFAULT_PROVIDER_NAME, provider);
}
public static void registerProvider(String name, Provider provider) {
providers.put(name, provider);
}
// 访问Service 的方法
public static com.staticFactory.Service newInstance() {
return newInstance(DEFAULT_PROVIDER_NAME);
}
public static com.staticFactory.Service newInstance(String name) {
Provider provider = providers.get(name);
if (null == provider) {
throw new IllegalArgumentException("No registered with name : " + name);
}
return provider.newService();
}
public void print() {
System.out.println("ok");
}
}
在书中只是定义了Provider 接口并没有写出如何获得实例对象的过程。所以自己就是实现了一个方法用于返回新的实例的实现类
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ProviderImp implements Provider {
public Service newService() {
try {
/*利用反射获取类构造器并破封(可以访问私有的构造)来创建新实例*/
Class<?> clazz = Class.forName("com.staticFactory.Services");
/*获取构造器*/
Constructor con = clazz.getDeclaredConstructor(null);
/*破封*/
con.setAccessible(true);
/*返回新实例*/
return (Services) con.newInstance(null);
} catch (ClassNotFoundException e) {
throw new RuntimeException("文件没找到");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
测试
public class TestForStaticFactory {
public static void main(String[] args) {
Provider provider = new ProviderImp();
// 注册
Services.registerProvider("ClientServer", provider);
// 创建实例
Service service = Services.newInstance("ClientServer");
service.print();
}
}
上面的代码,是服务提供者框架简单的实现,服务提供者框架是指一个系统:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并且把他们从多个实现中解耦出来。
4.创建参数化类型实例时,代码会更加简洁
Map<String,List<String>> m = new Map<String, List<String>>();
上面的段代码中很冗长,经过下面的实现可以让代码更简洁
public static <K,V> HashMap<K,V> newInstance() {
return new HashMap<K,V>();
}
//声明
Map <String,List<String>> m = HashMap.newInstance();
很显然声明变得更加简洁!!!