如果已经询问过,请链接并关闭此页。
我目前正在设计一个针对某个其他API的简化API的设计,这个API要复杂得多(且有潜在危险)。
考虑到相关的有些复杂的对象创建,我决定使用静态工厂方法来简化API,我现在有以下工作按预期工作:
public class Glue<T> {
private List<Type<T>> types;
private Glue() { types = new ArrayList<Type<T>>(); }
private static class Type<T> {
private T value;
/* some other properties, omitted for simplicity */
public Type(T value) { this.value = value; }
}
public static <T> Glue<T> glueFactory(String name, T first, T second) {
Glue<T> g = new Glue<T>();
Type<T> firstType = new Glue.Type<T>(first);
Type<T> secondType = new Glue.Type<T>(second);
g.types.add(firstType);
g.types.add(secondType);
/* omitted complex stuff */
return g;
}
}
如上所述,这可以按预期工作。当API用户( =其他开发者)输入Glue<Horse> strongGlue = Glue.glueFactory("2HP", new Horse(), new Horse());
时,他会得到他想要的内容。
我缺少的是如何强制执行Horse
- 或者在工厂方法中添加的任何内容 - 始终实现Serializable
和{{1} }?只需在使用此简化API的情况下,使用Comparable
将它们添加到工厂方法的签名中并不一定会在所有情况下强制执行此规则。这就是为什么我想将它们添加到类的定义中,然后相应地修改工厂方法。
PS:写这个问题没有马(绝对没有小马!)。
答案 0 :(得分:4)
你真的很亲密。这是我的解决方案
public class Glue<T extends Serializable & Comparable<T>> {
private List<Type<T>> types;
private Glue() { types = new ArrayList<Type<T>>(); }
private static class Type<T> {
private T value;
/* some other properties, omitted for simplicity */
public Type(T value) { this.value = value; }
}
public static <V extends Serializable & Comparable<V>> Glue<V> glueFactory(
String name, V first, V second) {
Glue<V> g = new Glue<V>();
Type<V> firstType = new Glue.Type<V>(first);
Type<V> secondType = new Glue.Type<V>(second);
g.types.add(firstType);
g.types.add(secondType);
/* omitted complex stuff */
return g;
}
}
public class Horse implements Serializable, Comparable<Horse> {
private static final long serialVersionUID = 1156763996034008367L;
@Override
public int compareTo(Horse o) {
return 0;
}
}
public class Cat { }
public static void main(String[] args) {
Glue<Horse> gh = Glue.glueFactory("2HP", new Horse(), new Horse());
Glue<Cat> gc = Glue.glueFactory("2C", new Cat(), new Cat()); // <--- Does not compile, as requested!!
}
此程序与您在这些方面的代码不同:
T
(glueFactory()
方法)重命名为V
。鉴于该方法是静态的,其类型参数与包含类类型参数无关,因此当两者具有不同的名称时,代码更清晰。implements Serializable & Comparable ...
)添加到V
和T
正如预期的那样,生成的程序会编译Glue.glueFactory("2HP", new Horse(), new Horse());
但拒绝Glue.glueFactory("2C", new Cat(), new Cat());
答案 1 :(得分:1)
我想唯一合适的解决方案是删除使用你提到的第二个API的可能性,并将你描述的类型约束添加到上面的静态工厂方法中。
如果您不能弃用第二个API,则无法强制执行此类约束。您当然可以在类中添加适当的接口实现,但第二个API不需要它,因此总会有一个漏洞可以漏掉。
答案 2 :(得分:0)
除了泛型类型边界(未经过重新调整)之外,如果你想要的话,可以进行运行时检查,即
if (first instanceof Comparable && first instanceof Serializable) {
// everything's fine...
} else {
throw new IllegalArgumentException("what are you doing?");
}