java的设计模式 - 静态工厂方法
静态工厂方法,也不知道为何叫这个名字。其实也就是一个静态函数,可以替代构造函数用。大名鼎鼎的 就大量使用这种模式,这是非常有用的模式。
比如是
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 (逃。
这样可以强制不使用继承,只能用组合。
以上