循环异构集合

时间:2018-03-21 12:11:54

标签: java oop design-patterns domain-driven-design

示例如下:我有Box需要填充一些Thing。我只对每件事的重量感兴趣。此外,除了重量,我需要正确识别我正在测量的东西。每种类型都有不同的Id类型。在这种情况下,我有玩具和水果,分别有ToyIdFruitId。最后,我需要能够打印物品标识符和物体重量。

问题:是否可以在不使用instanceof运算符的情况下访问ThingId上的特定方法(如示例)?

class Color{}
interface ThingId {}

class FruitId implements ThingId {
    String name;    //"apple", "orange", ...
    FruitId(String name){  this.name = name; }
    String getName(){ return this.name; }
}

class ToyId implements ThingId {
    String shape;   //"square", "circle", ...
    Color color;    //"red", "blue"...
    ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
    String getShape(){ return this.shape; }
    Color getColor(){ return this.color; }
}

class Thing{
    ThingId thingId;
    Integer weight;
    public Thing(ThingId thingId, Integer weight){
        this.thingId = thingId;
        this.weight = weight;
    }
    ThingId getThingId(){ return this.thingId; }
    Integer getWeight(){ return this.weight; }
}

class Box {
    Set<Thing> things = new HashSet<>();

    void addThing(Thing thing){
        this.things.add(thing);
    }

    Collection<Thing> getThings(){
        return this.things;
    }
}

class Program {
    public static void main(String[] args) {
        FruitId appleId = new FruitId("apple");
        Thing apple = new Thing(appleId, 1);
        ToyId cubeId = new ToyId("square", new Color());
        Thing cube = new Thing(cubeId, 22);

        Box box = new Box();
        box.addThing(apple);
        box.addThing(cube);

        for(Thing t : box.getThings()){
            System.out.print("Thing Id is: ");
            if(t.getThingId() instanceof FruitId) { //any other possibility than using instance of?
                process((FruitId)t.getThingId());
            }
            if(t.getThingId() instanceof ToyId){    //any other possibility than using instance of?
                process((ToyId)t.getThingId());
            }
            System.out.println("Weight is : " + t.getWeight());
        }
    }

    static void process(FruitId fruitId){
        System.out.println(fruitId.getName());
    }

    static void process(ToyId toyId){
        System.out.println(toyId.getShape() + toyId.getColor());
    }
}

更新

好的,我认为访客模式在这里很有用:

class Color{}
interface ThingId {
    void visitThingId(ThingIdVisitor visitor);
}

class FruitId implements ThingId {
    String name;    //"apple", "orange", ...
    FruitId(String name){  this.name = name; }
    String getName(){ return this.name; }

    @Override
    public void visitThingId(ThingIdVisitor visitor) {
        visitor.process(this);
    }
}

class ToyId implements ThingId {
    String shape;   //"square", "circle", ...
    Color color;    //"red", "blue"...
    ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
    String getShape(){ return this.shape; }
    Color getColor(){ return this.color; }

    @Override
    public void visitThingId(ThingIdVisitor visitor) {
        visitor.process(this);
    }
}

class Thing{
    ThingId thingId;
    Integer weight;
    public Thing(ThingId thingId, Integer weight){
        this.thingId = thingId;
        this.weight = weight;
    }
    ThingId getThingId(){ return this.thingId; }
    Integer getWeight(){ return this.weight; }
}

class Box {
    Set<Thing> things = new HashSet<>();

    void addThing(Thing thing){
        this.things.add(thing);
    }

    Collection<Thing> getThings(){
        return this.things;
    }
}

class ThingIdVisitor{
    void process(FruitId fruitId){
        System.out.println(fruitId.getName());
    }

    void process(ToyId toyId){
        System.out.println(toyId.getShape() + toyId.getColor());
    }
}

class Program {
    public static void main(String[] args) {
        FruitId appleId = new FruitId("apple");
        Thing apple = new Thing(appleId, 1);
        ToyId cubeId = new ToyId("square", new Color());
        Thing cube = new Thing(cubeId, 22);

        Box box = new Box();
        box.addThing(apple);
        box.addThing(cube);

        for(Thing t : box.getThings()){
            System.out.print("Thing Id is: ");

            t.getThingId().visitThingId(new ThingIdVisitor());

            System.out.println("Weight is : " + t.getWeight());
        }
    }
}

3 个答案:

答案 0 :(得分:2)

我真的没有得到你想要实现的目标。首先,我没有使用接口ThingId。其次,我认为你对接口和继承有点困惑。如果我是你,我会抬头polymorphism

无论如何,我建议你删除ThingId接口,让FruitIdToyId类扩展Thing类。由于您的收藏只存在Thing s,并且您的FruitToy类都扩展了此Thing类,因此实施getWeight()方法,您应该不再使用instanceof

但是,请阅读polymorphism

答案 1 :(得分:1)

您的界面ThingId必须提供您想要的相应方法。

如果您只想打印出信息,那么您可以像简单的一样使用

public String getInformation();

然后,实现可以返回与它们相关的信息,您只需在应用程序代码中使用ThingId即可。

顺便说一句:当您将Thing存储在HashSet时,请确保在所有equals实施中实施hashCodeThing

另外,我真的没有看到,为什么你需要一个Thing和一个ThingId,因为ThingId似乎不仅仅是一个简单的id而且实际上是一个东西。所以对我而言,似乎ThingId是多余的,所有这些都可以通过具有不同的Thing s来实现

答案 2 :(得分:1)

由于您在两个实例类型上调用相同的方法process,为什么不将该方法添加到ThingId接口本身。

通过这样做,你可以打电话:

t.getThingId().process();

而不是查找实例类型并调用相应的方法。