JAVA 静态工厂方法
2017-05-09 12:36
316 查看
静态工厂方法是一个类产生一个该类实例的静态方法,用于补充或取代类的构造器。
例如 Boolean 中有如下代码段,其中 valueOf 就是一个静态工厂方法。
注意,工厂模式中也有工厂方法,这和这里的静态工厂方法是不一样的。
使用静态工厂方法提供类的实例有以下一些优点。
1)静态工厂方法可以有不同于类名的名字,用户更容易从方法名猜测到其用途,例如 BigInteger 类中有一个静态工厂方法
该方法为用户返回一个很可能是质数的大整数。
2) 如上述 Boolean 类的方法 valueOf 所表现的, 静态工厂方法不需要新生成一个类的实例,它只是返回一个类的实例,这种方式常常能够提供效率上的改善。静态工厂方法常应用于单例模式中(Effective Java 中推荐使用枚举类型实现单例),保证一个类只被实例化一次,其它地方需要该类的实例是,总是返回同一个实例。
另外,在实现不可变类(immutable class)时,也常常用静态工厂方法提供类的实例。
3) 静态工厂方法可以返回当前类的子类实例,从而在不暴露子类的前提下,使用子类的实例,这也是构造方法不具备的功能。
抽象类 EnumSet 的一个静态工厂方法,根据枚举类型的大小,返回不同的 EnumSet 的子类实例。
这样做的另一个好处是解耦合,进而实现功能的易于扩展。例如如果将来有一种效率更好的 EnumSet 的子类时,则只需根据条件返回新的子类实例即可,而已使用该方法的代码并不产生做修改。
JDBC 作为一个 Service Provider 框架,也使用了静态工厂方法。 Service Provider 框架有三个必须的组成部分。
Service interface 将服务通过抽象统一声明,供客户端调用。由各个服务提供者(Provider)具体实现
Provider registration API 用于注册已实现了 Service interface 的 Provider,使得客户端可以访问它实现的服务
Service access API 常常通过一个静态工厂方法,让用户可以获得一个 Provider 的实例进行具体的使用。
结合 JDBC 框架
这段静态代码将在 JVM 加载该类时自动执行,这也是在建立数据库连接前,要显式调用
从以上的描述可以看出,静态工厂方法的作用主要是产生一个自身或者子类的实例,从而完善自身的功能和描述。
而工厂模式则是为了解耦,客户端在需要使用产品类的实例的时候,不需要通过 new 或者产品类的静态工厂方法来产生其实例,而是首先创建工厂类,然后通过工厂类提供的方法来得到产品类的实例。关于工厂模式的研究,将在下一篇博文中给出详细的介绍。
例如 Boolean 中有如下代码段,其中 valueOf 就是一个静态工厂方法。
//... public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false); //... public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
注意,工厂模式中也有工厂方法,这和这里的静态工厂方法是不一样的。
使用静态工厂方法提供类的实例有以下一些优点。
1)静态工厂方法可以有不同于类名的名字,用户更容易从方法名猜测到其用途,例如 BigInteger 类中有一个静态工厂方法
public static BigInteger probablePrime(int bitLength, Random rnd){ //... }
该方法为用户返回一个很可能是质数的大整数。
2) 如上述 Boolean 类的方法 valueOf 所表现的, 静态工厂方法不需要新生成一个类的实例,它只是返回一个类的实例,这种方式常常能够提供效率上的改善。静态工厂方法常应用于单例模式中(Effective Java 中推荐使用枚举类型实现单例),保证一个类只被实例化一次,其它地方需要该类的实例是,总是返回同一个实例。
public class Singleton { // 饿汉模式,JVM 只产生一个静态变量实例,避免线程安全问题,但增大了系统开销 private static final Singleton INSTANCE = new Singleton(); private Singleton() { //do something here } public static Singleton getInstance(){ return INSTANCE; } }
另外,在实现不可变类(immutable class)时,也常常用静态工厂方法提供类的实例。
3) 静态工厂方法可以返回当前类的子类实例,从而在不暴露子类的前提下,使用子类的实例,这也是构造方法不具备的功能。
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable { //... public <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType){ Enum<?>[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe); else return new JumboEnumSet<>(elementType, universe); } }
抽象类 EnumSet 的一个静态工厂方法,根据枚举类型的大小,返回不同的 EnumSet 的子类实例。
这样做的另一个好处是解耦合,进而实现功能的易于扩展。例如如果将来有一种效率更好的 EnumSet 的子类时,则只需根据条件返回新的子类实例即可,而已使用该方法的代码并不产生做修改。
JDBC 作为一个 Service Provider 框架,也使用了静态工厂方法。 Service Provider 框架有三个必须的组成部分。
Service interface 将服务通过抽象统一声明,供客户端调用。由各个服务提供者(Provider)具体实现
Provider registration API 用于注册已实现了 Service interface 的 Provider,使得客户端可以访问它实现的服务
Service access API 常常通过一个静态工厂方法,让用户可以获得一个 Provider 的实例进行具体的使用。
结合 JDBC 框架
java.sql.Connection是服务接口(Service interface),它定义了一系列的标准的服务内容,例如
prepareStatement(),commit()和
rollback()等,但却没有实现这些服务。服务提供者 Provider (Mysql,Oracle 等等)可以根据自己的特点实现这些服务内容,只要 Provider 相应的实现类 (例如
oracle.jdbc.driver.PhysicalConnection类,但我们并不关心这个具体实现类是什么) implements 了 JDBC 的标准接口
java.sql.Connection既能保证其可用性。
java.sql.DriverManager.getConnection()就是 Service access API 的静态工厂方法,它根据参数返回对应的 Connection,参数会指明需要返回的 Connection 的实现类。
java.sql.Driver对应 Service provider interface,Provider 提供该接口的实现类后,在实现类中有一段静态代码,调用
java.sql.DriverManager.registerDriver()方法将其自身注册到系统中,供用户使用。
static { try { if(defaultDriver == null){ defaultDriver = new OracleDriver(); java.sql.DriverManager.registerDriver(defaultDriver); } } catch (RuntimeException localRuntimeException) { } catch (SQLException localSQLException) { } }
这段静态代码将在 JVM 加载该类时自动执行,这也是在建立数据库连接前,要显式调用
Class.forName(“oracle.jdbc.driver.OracleDriver”);加载 Driver 类的原因。
从以上的描述可以看出,静态工厂方法的作用主要是产生一个自身或者子类的实例,从而完善自身的功能和描述。
而工厂模式则是为了解耦,客户端在需要使用产品类的实例的时候,不需要通过 new 或者产品类的静态工厂方法来产生其实例,而是首先创建工厂类,然后通过工厂类提供的方法来得到产品类的实例。关于工厂模式的研究,将在下一篇博文中给出详细的介绍。
相关文章推荐
- java高效编程一(静态工厂方法代替构造函数)
- java用静态工厂代替构造函数使用方法和优缺点
- Java代码设计思想之静态工厂方法..
- Effective.Java 读书笔记(1)静态工厂和构造方法
- Effective Java 进阶之路第一章(创建和销毁对象) 第一条(静态工厂方法)
- 为什么要在JAVA工厂模式中使用静态方法
- Think in Java 静态工厂方法学习总结
- Effective Java 1:考虑使用静态工厂方法代替构造器
- Java 基础 静态工厂方法
- Effective Java 学习笔记《一》 静态工厂方法
- Java 静态工厂方法
- Java学习笔记1:考虑用静态工厂方法代替构造器
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- Effective Java: 使用静态工厂方法
- Effective Java第一条:考虑用静态工厂方法替代构造器
- Java 静态工厂方法
- 设计模式:浅析 抽象工厂、工厂方法、简单(静态)工厂 java实现
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Java中用静态工厂方法代替构造器的优缺点
- java静态工厂(单个方法,也可以有多个方法)