通用接口的多个实现

时间:2017-01-07 09:39:59

标签: java oop

我正在创建一个界面说“汽车”

public interface Car {
    public void drive(int Speed); // for cars which do not have gears
}

有多种实现,如Bus,Truck等 然后在一个名为Trafic的主类中,应调用所有实现的驱动方法(顺序无关紧要)。 我有两种流量类设计选项:

1)要么为每个Car实现使用一个属性,这使得consrtuctor很难 维护和丑陋(有许多相同类型的参数以及通过添加新的Car实现它应该被更改的事实),如下所示:

public class Traffic {
  private Car bus;
  private Car truck;
  ...
  public Traffic(Car bus, Car truck,...){
    this.bus = bus;
    this.truck = truck;
   ...
  }

  public void run(){
     bus.drive();
     truck.drive();
     ...
  }

}

2)或将汽车列表传递给交通。然后,如果我想检查有关总线的其他内容,那么有时我需要找到Instance Of的实现。它会是这样的:

public class Traffic {
  private List<Car> cars;
    public Traffic(Car bus, Car truck,...){
    this.bus = bus;
    this.truck = truck;
   ...
  }
  public void run(){
    for(Car car : cars){
       car.drive();
     }
  }
}

我对这两种解决方案都不满意。还有其他解决方案吗?

2 个答案:

答案 0 :(得分:2)

你可以使用Varargs作为参数,你应该在你的集合中使用泛型它更安全。

public class Traffic {
  private List<Car> cars;
...
  public Traffic(Car... cars){
    this.cars = Arrays.asList(cars);
  }
...
}

如果您希望List没有Arrays.asList()返回的列表的限制,您可以这样做:

public class Traffic {
  private List<Car> cars;
...
  public Traffic(Car... cars){
    this.cars = new ArrayList<>();
    this.cars.addAll(Arrays.asList(cars));
  }
...
}

答案 1 :(得分:2)

  

如果我想查看有关总线

的其他内容该怎么办?

在多态设计中,您应该创建一个在更高级别调用的功能委托方法,并在那里放置特定于实现的逻辑。有时这意味着创建一个完整的迷你DI辅助类,为父类的多态实现提供额外的服务,这可能会让事情看起来有点奇怪,但同时在OOP中却没有真正的解决方法。 / p>

考虑以下类层次结构:

public abstract class Vehicle {
    public abstract void drive();
}

public abstract class Car extends Vehicle {
    public void drive() {
        System.out.println("Driving around...");
    }
    public void honkHorn() {...}
}

public final class Bus extends Car {
}

public final class Truck extends Car {
    @Override
    public void drive() {
        super.drive();
        honkHorn();
    }
}

在这里,我通过两个额外的功能扩充了您的课程层次:

  • 现在有一个共同的超级班Vehicle,因为也许你想扩展到也被驾驶的船只,但绝对不会像汽车一样。
  • Truck每次被驱动时都会鸣喇叭

后半部分是重要的一部分;多态的一个更大的好处是在子类中引入这样的额外功能。如果存在外部依赖关系并且需要进行状态检查 - 例如我们真的不想在高速公路上驾驶我们的船只 - 您可以在顶层引入帮助程序以为实现提供额外的细节。所以,像这样改变Vehicle ......

public abstract class Vehicle {
    public abstract void drive(Surface surface);
}

现在允许我们定义Boat ...

public abstract class Boat extends Vehicle {
    @Override
    public void drive(Surface surface) {
        if (surface.isWater()) {
            doDrive(surface);
        }
    }
    // this is needed to ensure that extending classes really do implement the driving capability!
    public abstract void doDrive(Surface surface);
}

将所有Boat实施的适用性限制为仅含水的表面。

为了将所有这些与你的Traffic类结合在一起,你现在可以开始考虑什么是适当的对象层次结构来处理这里给出的类建模的各个方面。例如,您可以在Traffic上定义Surface,并且该类仅处理在Vehicle上移动Lane s的实例,并且逻辑将查询例如。车辆的尺寸和速度要考虑这样的情况,例如公交车在从停车场接载乘客后可以切换车道,或者车道已经填满边缘并且行驶速度太慢而无法保证车道变换。

要回答您的问题,在内部您可能希望在任何情况下使用List<Vehicle>,因为这会为您的车辆提供订购,但Traffic类不应该列出车辆列表,如果Traffic代表高速公路,你真的不加入来自随机点的交通,而是从特定的交叉路口/交叉路口将车辆插入特定地点与高速公路相关。因此,您可能希望创建一些方法,以便在Vehicle的特定点中插入/移出Traffic。在这种情况下,内部列表可能应该包含包装器对象,以增加车辆信息与车辆在车道上的相对位置,以便更容易插入新车辆,并且通常在一个简单的循环中更新所有位置,但此帖现在是真的很长,我在这里假设很多... :))