本文共 1823 字,大约阅读时间需要 6 分钟。
参考:Effective Java 第二版 第二章
对于类而言,为了让客户端获取它自身的一个实例,最常用的方法就是提供一个公有构造器,还有一种方式是类提供一个公有的静态工厂放。它只是一个返回类的实例的静态方法。
注意:静态工厂方法与设计模式中的工厂方法不同。
静态工厂方法与构造器不同的优势包括:
如果构造器的参数本身没有确切地描述正被返回的对象,那么具有适当名称的静态工厂会更容易使用,产生的客户端代码也更容易阅读。如果BigInteger返回的可能是素数,但是使用BigInteger.probablePrime的静态工厂方法表示会更加清楚。一个类只能有一个带有指定签名的构造器,编程人员可以避开这一限制,通过提供两个构造器,参数列表只在参数类型的顺序上有所不同。这个的API,用户不知道该如何使用。
静态工厂方法有名称,可以不受上述限制。当一个类需要多个带有相同前面的构造器时,就用静态工厂方法代替构造器,并且慎重选择名称以便突出它们之间的区别。
可以使得不可变类可以使用余弦构建好的实例,或者将构建好的实例缓存起来,今次那个重复利用,从而避免创建不必要的重复对象。如果程序经常请求创建相同的对象,并且创建对象的代价很高,这项技术可以极大地提升性能。
静态工厂方法能够为重复的调用返回相同对象,有助于类总能严格控制在某个时刻哪些实例应该存在。这种类被称为实例受控的类。编写实例受控的类有几个原因。实例受控类可以使得类可以确保它是一个单例或者是不可实例化。它还使得不可变的类可以确保不会存在两个相等的实例。如果类保证了这一点,客户端就可以使用==操作符来代替equals方法,这样可以提升性能。枚举保证了这一点。
在选择返回对象的类时就有了更大的灵活性。这种灵活性的一种应用是,API可以返回对象,同时又不会使对象的类变成公有的。这项技术适用于基于接口的框架,因为在这种框架中,接口为静态工厂方法提供了自然返回类型。接口不能有静态方法,按照惯例,接口Type的静态工厂方法被放在一个名为Types的不可实例化的类。
例如:Java Collections Framework的集合接口有32个便利实现,分别提供了不可修改的集合、同步集合等等。几乎所有的这些实现都通过静态工厂方法在一个不可实例化的类(java.util.Collections)中导出。所有返回对象的类都是非公有的。
公有静态工厂方法所返回的对象的类不仅可以是非公有的,而且该类还可以随着每次调用而发生变化,这取决于静态工厂的参数值。只要是已生你妹的返回类型的子类型,都是允许的。为了提升软件的可维护性和性能,返回对象的类也可能随着发型版本的不同而不同。
静态工厂方法所返回的对象所属的类,在编写包含该静态工厂方法的类时可以不必存在。这种灵活的静态工厂方法构成了服务提供者框架的基础。服务提供者框架是指这样一个系统:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。
服务提供者框架中有三个重要的组件:服务接口,这是提供者实现的;提供者注册API,这是系统用来注册实现,让客户端访问它们的;服务访问API,是客户端用来获取服务的实例的。服务访问API一般允许但是不要求客户端指定某种选择提供者的条件。如果没有这样的规定,API就会返回默认实现的一个实例。服务访问API是灵活的静态工厂,它构成了服务提供者框架的基础。
服务提供者的第四个组件时可选的,服务提供者接口,这些提供者负责创建其服务实现的实例。如果没有服务提供者接口,实现就按照类名称注册,并通过反射方式进行实例化。
在创建参数化类型实例的时候,它们使代码变得更加简洁。在调用参数化类的构造器时,即使类型参数很明显,也必须指明,者通过要求接连两次提供类型参数。
类型参数越来越长,越来越复杂,冗长的说明也变得麻烦,有了静态工厂方法,编译器可以帮助找到类型参数,这被称为类型推导。
静态工厂方法的主要缺点在于:类如果不含公有的或者受保护的构造器,就不能被子类化。它们与其他的静态方法实际上没有任何区别。
转载地址:http://lgyai.baihongyu.com/