JAVA 静态工厂方法

来源:互联网 发布:linux 修改文件时间戳 编辑:程序博客网 时间:2024/05/22 01:46

静态工厂方法是一个类产生一个该类实例的静态方法,用于补充或取代类的构造器。
例如 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 或者产品类的静态工厂方法来产生其实例,而是首先创建工厂类,然后通过工厂类提供的方法来得到产品类的实例。关于工厂模式的研究,将在下一篇博文中给出详细的介绍。

0 0
原创粉丝点击