考虑到误用密封类,让我们看看下面的设计。
有两个模块: parser
(kotlin)-负责从字符串生成示例 processor
(java)-将原始传入数据泵入强类型存储器(即关系表)
字符串来自外部源到
processor processor
将其认可委托给
parser parser
创建不同类型的示例 [Banana, Nail, Shoe]
基于一些
rules X processor
基于某些属性将每个示例持久化到适当的表中 rules Y
在这里像这样使用密封类是否合适 parser
在那之后 processor
根据每个示例的具体类型做出决策?
// parser module exposes Item and its subclasses
sealed interface Item {
class Banana(/*state 1*/) : Item
class Nail(/*state 2*/) : Item
class Shoe(/*state 3*/) : Item
}
fun parse(value: String, rule: ParseRule): Item {
return when (true) {
rule.canParseBanana(value) -> rule.makeBananaFrom(value)
rule.canParseNail(value) -> rule.makeNailFrom(value)
rule.canParseShoe(value) -> rule.makeShoeFrom(value)
else -> throw RuntimeException("cannot parse")
}
}
// processor module makes decisions based on class
void process(String value){
Item item = parser.parse(value);
if (item instance of Item.Banana){
persistBanana((Item.Banana) item)
} else if ( ... )
// etc
} else {
throw new RuntimeException("Unknown subclass of Item : " + item.getClass())
}
}
我发现这种方法有点不对劲,因为越来越多的项的子类可能会导致设计灾难,但无法确定是否存在与此完全不同的密封类的“规范”用例。
当系统设计师更喜欢以下“类型较少”的东西时,密封类的适用性有什么限制:
class Item{
Object marker; // String or Enum
Map<String, Object> attributes;
}
// basically it is the same, but without dancing with types
void process(String value){
Item item = parser.parse(value);
if ("BANANA".equals(item.marker)){
persistBanana(item.attributes)
} else if (...){
// etc
}
}
1条答案
按热度按时间bis0qfac1#
您可以使用访问者模式提供
when
..is
java的风格方法。因为物品是密封的,所以你不需要
else
那样的话when
然后java代码可以创建访问者,而不是自己创建访问者instanceof
与一名律师核实else
,如果您添加了一个变体,那么您将添加一个方法,并得到提示,您的访问者的java实现需要新方法。