美文网首页
考虑用静态工厂方法(非设计模式)替代构造器--Effective

考虑用静态工厂方法(非设计模式)替代构造器--Effective

作者: 冰鱼飞鸟 | 来源:发表于2018-07-22 19:10 被阅读0次

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

    这里的静态工厂方法只是表示一个返回类的实例的静态方法。与设计模式中的不同。

    优势1.可以有自己的名字:可读性更高,不像构造器受重载规则的限制(相同参数返回不同对象的需求)。
    优势2.可以缓存实例:为重复的调用返回相同对象,避免重复创建对象。
    如Boolean.valueOf(boolean) 方法。

    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);
        }
    

    如果用valueOf创建Boolean对象则可以用==来比较,而不用equals,提升性能。
    但是Boolean不能保证只有a==b的时候,才有a.equals(b)为true,即可能a.equals(b)为true,但是a!=b,ab不是同一个对象.
    Java的枚举就保证了这一点(只有a==b的时候,才有a.equals(b)为true)

    优势3.可以返回所需对象的任何子类:对外开放的api可以隐藏一些实现类,只要提供工厂方法给外部。
    如java.util.Collections.unmodifiableList()提供创建不可修改集合的静态方法

    public static <T> List<T> unmodifiableList(List<? extends T> list) {
            return (list instanceof RandomAccess ?
                    new UnmodifiableRandomAccessList<>(list) :
                    new UnmodifiableList<>(list));
        }
    

    其中的UnmodifiableRandomAccessList,UnmodifiableList实现类就不用对外提供了,使得API非常简洁。也使得用户不得用具体的实现类的对象来接收这个方法的返回值,不管以后这个具体的类还在不在,增加了还是修改了,对用户都是不可见的。
    ps:用户指的使用这个api的代码。

    优势4.在使用泛型时可以提供类型推导功能。在java1.7后构造器中就能实现类型推导
    1.7之前:List<String> list = new ArrayList<String>();
    1.7之前 + 静态工厂方法 后可以:

    public static <K> List<K> getArrayList() {
            return new ArrayList<K>();
        } 
    List<String> list2 = getArrayList();
    

    1.7:List<String> list = new ArrayList<>();

    缺点1. 如果具体实现类不公开,则可能不能被继承扩展(因为其构造函数可能是private,default)。
    如上说的UnmodifiableRandomAccessList,对用户不可见,自然也没办法去继承扩展,不过组合优于继承。
    解决方法:不用继承,用组合(复合)。

    缺点2. 没有办法标识这个方法是普通的静态方法还是一个静态工厂方法。
    解决方法:遵循一些常用的静态工厂方法的命名习惯。
    如:valueOf,of,getInstance,newInstance,getType,newType.

    相关文章

      网友评论

          本文标题:考虑用静态工厂方法(非设计模式)替代构造器--Effective

          本文链接:https://www.haomeiwen.com/subject/hiymjftx.html