假设我要在一个表中显示一个库存项目列表(使用Java)。域模型由抽象基类StockItem组成,各种其他类型的库存项目都从该基础类派生。 StockItem提供了一个最小接口(interface)(getId()和getDescription()),但除此之外,子类可能会有很大的不同。
如果我将自己限制在StockItem上定义的方法上,将无法向用户提供足够的详细信息,因此这意味着某些列将引用不适用于某些行的字段(例如,实物是可计数的,此计数应出现在表格中,而预期也会出现在表格中的服务项目则不可计数,在这种情况下,应显示“N/A”或类似内容。
以“Countable”为例,在我看来,有两种解决方案(但是请记住,Countable并不是唯一涉及的接口(interface))。
这两种方法对我来说似乎都是反模式,我很想听听可能会采用的其他更高级的方法。我怀疑这没有万能的法宝,但是如果其他语言具有使此类事情变得更轻松的功能,我也很想听到它们(不过出于普遍的兴趣,我不会在任何时候重新实现该系统不久:)
谢谢,
菲尔
最佳答案
适配器图案
在您的StockItem类中添加方法:
/**
* Adapt the current instance to the type
* denoted by clazz else return null
* ...
*/
public <T> T adapt(Class<T> clazz){
if( clazz.isInstance(this)){
return (T)this;
}
return null;
}
这将被所有子类继承,并允许调用者安全地转换类型。
不要被泛型推迟了,只是说我希望此方法返回一个与clazz参数类型相同的实例。
现在,您的表提供程序可以实现以下内容:
public String getColumnText(Object cell, int columnIndex) {
if (cell instanceof StockItem) {
StockItem item = (StockItem) cell;
switch(columnIndex) {
case ID:
return item.getID;
case DESCRIPTION:
return item.getDescription;
case COUNT:
Countable countableItem = item.adapt(Countable.class);
return countableItem == null ? "N/A" : countableItem.getCount();
}
}
return "N/A";
}