假设:
IA
。B
,其参数为IA
的实例,其行为取决于该IA
的类型,含义(伪代码,没有特定的语言,[即使我使用Python])
class B{
IA ia;
B(IA ia){
this.ia = ia;
}
doStuff(){
if(type(this.ia)==A1){
print("A1");
}
if(type(this.ia)==A2){
print("A2");
}
}
}
我意识到我可以在foo
上添加一些公共方法ia
,因此代码可以简化为
class B{
IA ia;
B(IA ia){
this.ia = ia;
}
doStuff(){
this.ia.foo();
}
}
我的问题是双重的:
如果我(出于某种原因)无法更改IA
(也就是说,我不能添加foo()
)是实现该目标的正确设计?
如果允许我更改IA
,那么正确的(可伸缩的)设计是什么,但是现在A1
,A2
等重复同样的问题,这意味着< / p>
最终所需的行为是
class B{
IA ia;
B(IA ia){
this.ia = ia;
}
doStuff(){
if(type(this.ia)==A1){
if(type(this.ia.iz)==Z1){
print("A1Z1");
print("unique treatment");
}
if(type(this.ia.iz)==Z2){
print("A1Z2");
print("special treatment");
}
}
if(type(this.ia)==A2){
if(type(this.ia.iz)==Z1){
print("Z1A2");
print("one of a kind treatment");
}
if(type(this.ia.iz)==Z2){
print("Z2A2");
print("Wow treatment");
}
}
}
}
,并且可以重复多次。
请注意,A1和A2的Z1和Z1相同!。再一次,同样可以继续进行,IZ
可以包含具有独特行为的几种类型的IX
我想知道情况2是否完全是模块化的,从某种意义上说,行为对于每种类型组合都是唯一的,并且无法将行为真正提取到更抽象的水平。
我仍然不喜欢类型检查,想知道是否可以做一些看起来更好的事情。
答案 0 :(得分:1)
您可能想看一下访问者模式(https://en.wikipedia.org/wiki/Visitor_pattern)。这确实假设您可以更改IA
和朋友来实现accept
方法
答案 1 :(得分:0)
我认为您正在寻找的是Tagged Union Types。还考虑Do union types actually exist in python?
一些例子可能是Kotlin的Sealed Classes and When Statement。或Scala的Case Classes and Sealed Traits。
如果您使用的是Java,则使用Paguro进行设置会有些麻烦。
interface Wheeled { }
class Beetle implements Wheeled { }
class Truck implements Wheeled { }
// Makes a union class.
static class Beetle_Truck extends OneOf2<Beetle,Truck> {
private Beetle_Truck(Object o, int n) {
super(o, Beetle.class, Truck.class, n);
}
static Beetle_Truck ofBeetle(Beetle b) {
return new Beetle_Truck(b, 0);
}
static Beetle_Truck ofTruck(Truck t) {
return new Beetle_Truck(t, 1);
}
}
// Here's where we use it.
@Test public void testBeetleTruck() {
Beetle_Truck bt1 = Beetle_Truck.ofBeetle(new Beetle());
Beetle_Truck bt2 = Beetle_Truck.ofTruck(new Truck());
assertEquals("b", bt1.match(beetle -> "b",
truck -> "t"));
assertEquals("t", bt2.match(beetle -> "b",
truck -> "t"));
}
请注意,甲壳虫和卡车根本不需要实现公共接口。对于第二个问题,您可以执行与OneOf2类似的OneOf4。