在一篇Guava的presentation中,Google提到了一种叫“Utility Object pattern”的模式。
return Joiner.on(", ").skipNulls().join("one", null, "two", "three");
|-- 1 ---|-- 2 ------|-- 3 ----------------------------|
return Splitter.on("|").omitEmptyStrings().split("|Harry||Ron|||Hermione ||");
|-- 1 --|-- 2 -------------|-- 3 ------------------------------|
通过1
得到一个初始的、默认的utility对象,通过2
可以得到utility对象的一个“变种”,
再通过3
最后求值。
这种API看起来更简洁。用户不用知道不同变种对应的utility类。
实现上,2
中的方法,比如skipNulls()
,会返回一个新对象,或者修改对象的属性并返回它。
public Joiner skipNulls() {
return new Joiner(this) {//通过传入的this可以“继承”上一个Utility对象的某些特性
@Override
public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
//...
}
//...
}
}
public Splitter omitEmptyStrings() {
//直接构造相应的Utility对象
return new Splitter(strategy, true, trimmer, limit);
}
ComparisonChain是另一个有趣的例子。
Comparator<Person> comparator = new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return ComparisonChain.start().compare(p1.exp, p2.exp).compare(p1.age, p2.age).result();
}
};
使用ComparisonChain时,不会创建新的ComparisonChain对象。
ComparisonChain也支持“short circuit(短路)”。
当p1.exp
和p2.exp
的比较有结果时(不等于0),就不会再去比较age
。
public abstract class ComparisonChain {
private ComparisonChain() {}
public abstract ComparisonChain compare(Comparable<?> left, Comparable<?> right);
public abstract <T> ComparisonChain compare(
@Nullable T left, @Nullable T right, Comparator<T> comparator);
public abstract ComparisonChain compare(int left, int right);
// ...
public static ComparisonChain start() {
return ACTIVE;
}
private static final ComparisonChain ACTIVE =
new ComparisonChain() {
@Override
public ComparisonChain compare(Comparable left, Comparable right) {
return classify(left.compareTo(right));
}
@Override
public <T> ComparisonChain compare(
@Nullable T left, @Nullable T right, Comparator<T> comparator) {
return classify(comparator.compare(left, right));
}
@Override
public ComparisonChain compare(int left, int right) {
return classify(Ints.compare(left, right));
}
ComparisonChain classify(int result) {
return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE;
}
@Override
public int result() { return 0;}
};
private static final ComparisonChain LESS = new InactiveComparisonChain(-1);
private static final ComparisonChain GREATER = new InactiveComparisonChain(1);
private static final class InactiveComparisonChain extends ComparisonChain {
final int result;
InactiveComparisonChain(int result) { this.result = result; }
@Override
public ComparisonChain compare(@Nullable Comparable left, @Nullable Comparable right) {
// 不会做任何比较运算,直接返回自己
return this;
}
@Override
public ComparisonChain compare(int left, int right) { return this; }
@Override
public int result() { return result; }
}
ComparisonChain定义了3个静态变量,ACTIVE
、LESS
和GREATER
。
所有的比较都基于这3个对象,不会新建新的ComparisonChain对象。
只有ACTIVE
会做真正的比较。一旦ACTIVE
有了比较结果,就会返回LESS
或者GREATER
对象。
后续的比较都会基于LESS
或者GREATER
,它们不会做任何比较运算(这就是某种意义上的“短路”)。