Item 1: Consider static factory methods instead of constructors (多考虑使用静态工厂方法而不是构造方法)
使用静态工厂方法有以下几点好处:
One advantage of static factory methods is that, unlike constructors, they have names.(一个好处是与构造方法不同,静态工厂方法有名字)。 使用静态工厂方法可以说明客户程序员理解程序。因为静态工厂方法可以去一些比较有意义的名字使代码可读性更高。比如
BigInteger(int, int, Random) 这个构造方法是返回一个很有可能是质数的BigInteger, 从这个构造方法 根本不能很明确的得到这一信息。这时候可以采用一个静态工厂方法来说明理解,如BigInteger.probablePrime。 静态方法的名字 probablePrime 很明确地告诉了客户程序员这个方法是干什么的。
A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked. (第二个好处是,与构造方法不同,静态工厂方法不需要再每次被调用的时候创建一个新的对象,这个类似于设计模式中的Flyweight 享元模式)
静态工厂方法可以在多次调用的时候返回同一个对象,可以让类严格地管理它的实例(什么时候应该销毁,什么时候应该创建等等)。这种类可以叫做 instance-controlled. Instance control可以让类实现单例(Item 3),不可实例化(Item 4)等等的特殊需求。它同样允许,不可变类(Item 15)的实现 以保证没有两个相同实例 存在。 那么也就意味着 a.equals(b) 当且仅当 a==b的时候成立。所以客户程序员可以使用==代替 equals方法,这样可以提高程序的运行效率。
A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.(使用静态工厂方法,与构造方法不同,可以返回其返回类型的任意子类型)
这一优点保证了程序的灵活性,这也是service provider frameworks(服务提供商框架)的基础之一。
服务提供商框架一共有四个部分组成:
1. Service interface:服务接口,通过抽象统一声明,由服务提供者实现。
2. provider registration API:服务提供者注册API,用于系统注册服务提供者,使得客户端可以访问它实现的服务
3. Service access API:服务访问API,用户客户端获取相应的服务。
4. Service provider interface(Optional): 服务提供者接口,这些服务提供者负责创建其服务实现的实例。
对于JDBC来说,Connection就是服务接口,Orcale、SQLServer、MySQL等是服务提供者,它们实现相应的服务接口;DriverManager.registerDriver是提供者注册API,向DriverManager注册给定驱动程序;DriverManager.getConnection是服务访问API;Driver就是服务提供者接口。
下面是书中给出的一个服务提供商框架的例子
- // Service provider framework sketch
- // Service interface
- public interface Service {
- ... // Service-specific methods go here
- }
- // Service provider interface
- public interface Provider {
- Service newService();
- }
- // Noninstantiable class for service registration and access
- public class Services {
- private Services() { } // Prevents instantiation (Item 4)
- // Maps service names to services
- private static final Map<String, Provider> providers =
- new ConcurrentHashMap<String, Provider>();
- public static final String DEFAULT_PROVIDER_NAME = "<def>";
- // Provider registration API
- public static void registerDefaultProvider(Provider p) {
- registerProvider(DEFAULT_PROVIDER_NAME, p);
- }
- public static void registerProvider(String name, Provider p){
- providers.put(name, p);
- }
- // Service access API
- public static Service newInstance() {
- return newInstance(DEFAULT_PROVIDER_NAME);
- }
- public static Service newInstance(String name) {
- Provider p = providers.get(name);
- if (p == null)
- throw new IllegalArgumentException(
- "No provider registered with name: " + name);
- return p.newService();
- }
- }
A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances. (可以使创建参数化类型实例更佳简洁)
比如:创建HashMap时,就需重复输入类型参数
- Map<String, List<String>> m = new HashMap<String, List<String>>();
使用静态工厂方法可以解决这一问题
- //静态工厂方法,类型参数只需要在这里写一遍即可
- public static <K, V> HashMap<K, V> newInstance() {
- return new HashMap<K, V>();
- }
- //创建对象时,就不用重复类型参数了。
- Map<String, List<String>> m = HashMap.newInstance();
静态工厂方法也有一些不足之处:
The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed(最大的缺点是,如果类只提供了静态工厂方法而没有提供public和protected的构造器的话,不能派生子类)
A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods. (第二个缺点就是使用静态工厂方法,客户程序员从文档中很难将其与其他静态方法分辨)第二个缺点涉及到javadoc,因为javadoc不会对静态工厂方法进行特殊处理,所以客户程序员不能像查询构造方法一样 很快的找到静态工厂方法。
以下是一些常用的静态工厂方法的命名方法:
• valueOf—Returns an instance that has, loosely speaking, the same value as its
• of—A concise alternative to valueOf, popularized by EnumSet (Item 32).
• getInstance—Returns an instance that is described by the parameters but
• newInstance—Like getInstance, except that newInstance guarantees that
• getType—Like getInstance, but used when the factory method is in a different
• newType—Like newInstance, but used when the factory method is in a different
总体来说,静态工厂方法和构造器都有其自己的作用,但是一般说来还是优先使用静态工厂方法。