欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java的设计模式 - 静态工厂方法

程序员文章站 2022-12-22 22:33:47
静态工厂方法,也不知道为何叫这个名字。其实也就是一个静态函数,可以替代构造函数用。大名鼎鼎的 [guava](https://github.com/google/guava) 就大量使用这种模式,这是非常有用的模式。 ......

静态工厂方法,也不知道为何叫这个名字。其实也就是一个静态函数,可以替代构造函数用。大名鼎鼎的 就大量使用这种模式,这是非常有用的模式。

比如是

integer i = integer.valueof(123);
boolean bool = boolean.valueof(true);
//guava 的方法
concurrentmap<string,integer> concurrentmap = maps.newconcurrentmap();
arraylist<integer> array = lists.newarraylist(1,2,3,4,5);

那么为什么要用静态工厂方法呢?
《effective java》解释得挺好的,下面我就进行“人类的本质”,并加点个人的见解。

静态工厂方法,可以不用创建新的对象

可以去看下 integer.valueof 函数

public static integer valueof(int i) {
    if (i >= integercache.low && i <= integercache.high)
        return integercache.cache[i + (-integercache.low)];
    return new integer(i);
}

如果是 -128 到 127,通过 valueof 构造对象能从对象池中直接获取,避免了对象重复构建!
如果是 boolean 对象,只有 true 和 false 效果就更明显了。

有名字就是好

比如有个 user 类,有 name,address,email等字段。有些数据只需 name、和 email 字段就可以了,有些字段只需 name 和 address 字段就可以了。但这确实不能创建两个相同类型的构造器!但你可以创建newnamewithemail 或者 newnamewithaddress 的静态工厂函数。方便!

免去繁琐,不用写太多的通配符

这个也是被 guava 发扬广大,
比如:正常构造一个 hashmap

map<string,list<string>> map = new hashmap<string,list<string>>();

前面类型都定义好了,为毛还要写 new hashmap<string,list<string>>();这样的一大串东西;
guava中只要这样就可以了,而且还是类型安全的!

map<string,list<string>> map = maps.newhashmap();

怎样做到的呢?看下以前版本的实现。

public static <k, v> hashmap<k, v> newhashmap() {
        return new hashmap<k,v>();
}

其实 ,java 官方也发现这个问题的 java 7 在这样一种语法糖

map<string,list<string>> map = new hashmap<>();

java 9 后 有了 var 语法糖。可以写成

var map = new hashmap<string,list<string>>();

静态工厂函数的这个优势可有可无了

可以返回原返回类型的任何子类型

比如 enumset 根据 universe 数组的长度可以返回不同类型的 enumset

public abstract class enumset<e extends enum<e>> extends abstractset<e>
    implements cloneable, java.io.serializable {

    enumset(class<e>elementtype, enum[] universe) {
    }

    public static <e extends enum<e>> enumset<e> noneof(class<e> elementtype) {
        if (universe.length <= 64)
            return new regularenumset<>(elementtype, universe);
        else
            return new jumboenumset<>(elementtype, universe);
    }
}

确实是有点用,这种用法我是用得比较少。不喜欢用这样方式。觉得还不如不封装(逃

静态工厂方法的缺点

个人觉得,没啥缺点,甚至觉得每个类最好用静态工厂函数替代构造函数!最好还是把构造函数变成 private (逃。
这样可以强制不使用继承,只能用组合。

以上