倾斜的更好的替代方案?

时间:2013-12-03 23:03:41

标签: java

这会是一个很好的替代模式......?

注意:每次我想访问子类的方法,即((Bicycle)vehicles[1]).getSaddles()位时,我都希望避免向下转换对象。 Vehicle的子类只有一个带有值和一些getter的构造函数才会很简单,但getter却不一样。

public class Main {

    Vehicle[] vehicles;

    public static void main(String[] args) {
        new Main();
    }

    private Main() {

        DataStuff data = new DataStuff();

        vehicles = new Vehicle[data.getNext()];

        int i=0;
        while(i<vehicles.length) {
            int type = data.getNext();
            if (type == 1) {
                vehicles[i] = new Car(VehicleType.car, data);
            } else if (type == 2) {
                vehicles[i] = new Bicycle(VehicleType.bicycle, data);
            }
            i++;
        }

        if (vehicles[1].type.equals(VehicleType.bicycle)) {
            System.out.println(vehicles[1].type.toString() + ", number of saddles:" + ((Bicycle)vehicles[1]).getSaddles());
        }

    }

    public class DataStuff {

        private int[] data = new int[] {2, 1, 4, 5, 1, 4, 2, 2, 1, 1};
        private int pointer = 0;

        public int getNext() {
            return data[pointer++];
        }
    }

}

...

public class Vehicle {

    public VehicleType type;

    public Vehicle(VehicleType type) {
        this.type = type;
    }

}

...

public enum VehicleType {
    car,
    bicycle 
}

...

public class Bicycle extends Vehicle {

    private int wheels;
    private int bells;
    private int saddles;

    public Bicycle(VehicleType type, DataStuff data) {
        super(type);
        wheels = data.getNext();
        bells = data.getNext();
        saddles = data.getNext();
    }

    public int getWheels() {
        return wheels;
    }

    public int getBells() {
        return bells;
    }

    public int getSaddles() {
        return saddles;
    }

}

...

public class Car extends Vehicle {

    private int wheels;
    private int seats;
    private int engines;
    private int doors;

    public Car(VehicleType type, DataStuff data) {
        super(type);
        wheels = data.getNext();
        seats = data.getNext();
        engines = data.getNext();
        doors = data.getNext();
    }

    public int getWheels() {
        return wheels;
    }

    public int getSeats() {
        return seats;
    }

    public int getEngines() {
        return engines;
    }

    public int getDoors() {
        return doors;
    }

}

更新1

假设对象ObjectA和ObjectB完全不同(ish),但我必须以通用方式存储它们。 ObjectA可以是一个国家的定义,ObjectB可以是一个树......

更新2

(我还更新了上面的psuedo代码以修复错误并使其更明显)我希望不要写太多代码,因为我不希望人们陷入我的测试用例的细节,但是上面的代码接近我需要实现的目标。

我的问题可能措辞不多。我会尽量不那么模糊。

所以...我有一个关于任意对象的数据,这些数据是以共享属性的随机顺序(我上面的代码虽然没有反映这一点)。我需要能够在解析int []之后遍历对象并获取每个对象的特定数据......但是,我想避免所有我需要做的向下转换(例如{{1声明)。

什么是好的替代模式?或者这样可以吗?我不必拥有巨大的if else块作为int []中的数据(不要担心DataStuff类只是一个简单的例子)将全部基于查询生成(也未在上面显示)代码)将由实现提供,因此开发人员将知道他期待什么(开发人员,我的意思是我无论如何大声笑......)。

我希望这足以说明我想要实现的目标。

2 个答案:

答案 0 :(得分:3)

考虑到您的“国家或树”评论,我认为您正在体验名为"Object-relational impedance mismatch"的内容。问题是静态类型的本质和多态性强加了现实世界并不总是(或经常)服从的等级刚性。有静态类型系统的替代方案来组织这些属性。您可以添加Map<String, Object>字段来存储任意字段(这是有多少库将Java映射到更动态的信息系统,如NoSQL或Graph数据库)。

考虑到JVM(读取编译的字节代码)是动态环境这一事实,你也可以接受向下转换,它并不像你想象的那样繁重。

在您的原始示例中(假设BaseObject是一个接口),您可以为每个类添加(技术上覆盖)toString()实现(无需检查类型)

答案 1 :(得分:3)

在不知道你的对象模型或工作的情况下,你的对象正在做什么,我建议你只需在你的基类上添加一个抽象方法并覆盖该方法来做适当的事情。这是基本的多态行为。

abstract class ChessPiece { 
    abstract void move(Board board);
}

class Knight extends ChessPiece { 
    @Override 
    public void move(Board board) { 
    //...weeee, I'm a Knight
    }
}

class Bishop extends ChessPiece { 
    @Override 
    public void move(Board board) { 
    //...weeee, I'm a Bishop
    }
}

如果你发现自己正在投掷并使用instanceof,那么这通常表明你做错了。

<强>更新

在这种情况下仅打印马鞍详细信息可能需要向下转换,但为什么不在每个toString上使用重写的Vehicle方法并打印出Bicycle对象?

    if (vehicles[1].type.equals(VehicleType.bicycle)) {
        System.out.println(vehicles[1]);
    }

   public class Bicycle extends Vehicle { 

       @Override
       public String toString() { 
          return this.saddles;
       }
   }

如果这还不够,我想你可以在Bicycle上编写一个静态方法,它接受一个自行车并输出它的马鞍信息,并简单地在你的打印语句中调用这样的方法:

System.out.println(vehicles[1].type.toString() + ", number of saddles:" + Bicycle.getSaddleInfo(Bicycle.class.cast(vehicles[1])));