如何为每种类型组合创建具有唯一行为的树层次结构?

时间:2019-02-23 22:04:54

标签: oop design-patterns

假设:

  1. 有些模块的接口为IA
  2. 有一个模块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();
    }
}

我的问题是双重的:

  1. 如果我(出于某种原因)无法更改IA(也就是说,我不能添加foo())是实现该目标的正确设计?

  2. 如果允许我更改IA,那么正确的(可伸缩的)设计是什么,但是现在A1A2等重复同样的问题,这意味着< / 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是否完全是模块化的,从某种意义上说,行为对于每种类型组合都是唯一的,并且无法将行为真正提取到更抽象的水平。

我仍然不喜欢类型检查,想知道是否可以做一些看起来更好的事情。

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。