考虑使用静态工厂方法替代构造方法

ε祈祈猫儿з 提交于 2020-01-14 16:02:33

        一个类允许客户端获取其实例的传统方式是提供一个公共构造方法,其实还有另一种技术应该成为每个程序员工具箱的一部分,一个类可以提供一个公共静态工厂方法,它只是返回类实例的静态方法。

      举一个简单的例子,java.lang包中的Boolean 对象,是boolean基本类型的包装类,此方法将boolean基本类型转换为boolean对象引用:

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

类可以为客户端提供静态工厂方法,而不是公共构造方法。提供静态工厂方法而不是公共构造方法有优点也有缺点。

静态工厂方法的第一个优点是,与构造方法不同,他们是有名字的,如果构造方法的参数并不秒数被返回的对象,则具有精心选择名称的静态工厂方法更易于使用,并且生成的客户端代码也更易于阅读,

例如:

假设我们需要写一个产生随机数的类RandomIntGenerator,该类有两个成员属性:最小值min和最大值max,

假设我们的需求是需要创建三种类型的RandomIntGenerator对象,

1.大于min,小于max;

2.大于min,小于Integer.MAX_VALUE;

3.大于Integer.MAX_VALUE;

如果我门不使用静态工厂方法,代码一般如下设计:


/**
 * @author CMQ
 */
public class RandomIntGenerator {
    /**
     * 最小值
     */
    private int min=Integer.MAX_VALUE;
    /**
     * 最大值
     */
    private int max=Integer.MAX_VALUE;

    /**
     * 大于min  小于max
     * @param min
     * @param max
     */
    public RandomIntGenerator(int min,int max){
        this.min= min;
        this.max=max;
    }

    /**
     * 大于min小于Integer.MAX_VALUE
     * @param min
     */
    public RandomIntGenerator(int min){
        this.min=min;
    }

    /**
     * 这里应为方法形参相同,导致报错
     * 大于Integer.MAX_VALUE 小于max
     * @param max
    public RandomIntGenerator(int max){
        this.max=max;
    }
     */

}

观察以上代码,我们发现,以上代码不仅可读性差( new RandomIntGenerator(1,10) 与 new RandomIntGenerator(10) ,不查文档,不看注释很难知道其创建对象的具体含义),而且再设计最后一个构造方法的时候,还报错了,因为已经存在一个参数一致的工作方法了,提示重复定义;

那么假设我门使用今天静态工厂方法会怎么样,如下所示:


/**
 * @author CMQ
 */
public class RandomIntGenerator {
    /**
     * 最小值
     */
    private int min=Integer.MAX_VALUE;
    /**
     * 最大值
     */
    private int max=Integer.MAX_VALUE;

    /**
     * 大于min  小于max
     * @param min
     * @param max
     */
    public RandomIntGenerator(int min,int max){
        this.min= min;
        this.max=max;
    }

    /**
     * 大于min小于Integer.MAX_VALUE
     * @param min
     */
    public RandomIntGenerator(int min){
        this.min=min;
    }

    /**
     * 这里应为方法形参相同,导致报错
     * 大于Integer.MAX_VALUE 小于max
     * @param max
    public RandomIntGenerator(int max){
        this.max=max;
    }
     */


    /**
     * 大于min  小于max
     * @param min
     * @param max
     * @return
     */

    public static RandomIntGenerator between(int min,int max){
        return new RandomIntGenerator(min,max);
    }

    /**
     * 大于min 小于 Integer.MAX_VALUE
     * @param min
     * @return
     */

    public static RandomIntGenerator biggerThan(int min){
        return new RandomIntGenerator(min,Integer.MAX_VALUE);
    }

    /**
     * 大于Integer.MAX_VALUE 小于 max
     * @param max
     * @return
     */

    public static RandomIntGenerator smallerThan(int max){
        return new RandomIntGenerator(Integer.MAX_VALUE,max);
    }


}

成功满足需求:创建三种类型的RandomIntGenerator对象,而且创建对象的时候代码可读性比使用构造方法强

        静态工厂方法的第二个优点是,与构造方法不同,它们不需要每次调用都创建一个对象。这允许不可变的类使用预先构建的实例,或者在构造时缓存实例,并反复分配他们以避免不必要的重复对象,Boolean.valueof(boolean) 方法说明了这种方法,他从不创建对象,这种技术类似与 flyweight (享元)模式,如果经常请求等价对象,那么它可以极大的提升性能,特别是创建他们非常昂贵的情况下,

       静态工厂方法的第三个优点是,与构造方法不同,他的返回类型可以是任何子类型的对象,为你选择返回对象的类时候提供很大的灵活性;

      静态工厂方法的第四个优点是返回对象的类可以根据输入参数的不同而不同,声明返回类型的子类都是允许的,返回对象的类也可以随每次发布而不同;

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!