抽象类的集合(或类似的东西......)

Pet*_*ter 7 java collections inheritance enums subclass

情景

我正在制作一个涉及汽车的Java程序.

注意:我已经简化了这种情况(尽我所能),使其更通用,更容易理解.我实际上并不是在和汽车打交道.

我创建了一个Cars类,它是一个Car对象的集合.

Car对象有一个speed(double)和一个year(int).构造函数将year作为参数,例如:

public class Car {
    private int year;
    private double speed;

    public Car(int year) {
        this.year = year;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个棘手的部分......汽车必须有一种(让我们说Corvette或Clunker).克尔维特将拥有speed0.9和难有起色将有一个speed0.1.如果Car没有指定它应该是什么样的汽车,就永远无法实例化.所以,现在,要创造一辆汽车,我们有:

Car car = new Car(1998, Corvette);
Run Code Online (Sandbox Code Playgroud)

我们刚刚创建的克尔维特将是一个Car具有对象speed0.9.

问题

我的实际情况涉及更多种类的汽车,每辆汽车除此之外还有几个特定的​​属性speed(也许还有字段color,numDoorsfuelTankSize).有这么多种车(每种都有自己的特定属性),代码变得比我想要的更复杂.

可能的解决方案

  1. 我可以与子类的工作,那就是,有一个抽象Car多数民众赞成通过扩展分类CorvetteClunker,但后来我有一个使用的问题,Cars对象(因为我不能做的东西的集合,不能被实例化).见下面的编辑.

  2. 使用枚举(例如CarKind)似乎需要几个凌乱的switch语句:

    • 填充speed每辆车的领域
    • CarCars类中创建对象
    • 等等

你可以如何帮助

我正在寻找一种允许单个Cars类包含每个Car对象的解决方案.我想要不同的集合(比如Corvettes,Clunkers).我也在寻找一个解决方案,它允许创建Car基于个人的车种...如前面提到的属性的对象,创建一个新的Car种类Corvette将导致speed0.9.应该没有其他方法来指定汽车speed.

在这种情况下有最好的做法吗?我的例子清楚了吗?

谢谢.

编辑:我不想要抽象Car对象集合的原因是因为集合的目的是Cars创建和操作Car对象,而不管它们的种类. Car抽象似乎使这复杂化.如果您认为这是最佳解决方案,请相应地回答.

Dar*_*Teo 11

我正在寻找一个允许单个Cars类包含每个Car对象的解决方案.我不想要不同的系列(如Corvettes,Clunkers).我也在寻找一种解决方案,允许根据单个汽车类型的属性创建Car对象......如前所述,创建一辆新型Corvette汽车将导致0.9的速度.应该没有其他方法来指定汽车的速度.

哦,男孩哦,男孩有很多方法可以解决这个问题,我们可以一整天都去!我会做一次大脑转储,希望对你来说不会太多.


解决方案1:使用策略.

策略基本上是将重度可替代逻辑与另一个类分开的一种方法.在这种情况下,每辆汽车都需要以不同的方式创建.一个策略是完美的.

对不起,如果我偶然混入一些C#...自从我编写java以来​​已经很久了.

public interface CarCreationStrategy{
   void BuildCar(Car theCar);
}

public class CorvetteStrategy implements CarCreationStrategy{
   public void BuildCar(Car theCar){
      theCar.Type = "Corvette";
      theCar.Speed = 0.9;
      theCar.Comments = "Speedster!";
   }
}

public class ToyotaStrategy implements CarCreationStrategy{
   public void BuildCar(Car theCar){
      theCar.Type = "Toyota";
      theCar.Speed = "0.5";
      theCar.Comments = "Never dies, even if you drop it from the top of a building";
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用汽车构造函数传递策略.

public class Car{
   // Variables ...

   public Car(CarCreationStrategy strategy, int year){
      strategy.BuildCar(this); // Implements your properties here.
      this.year = year;
   }
}
Run Code Online (Sandbox Code Playgroud)

所以,你现在得到的是如此棒!

List<Car> cars = new List<Car>();
cars.Add(new Car(new CorvetteStrategy(),1999));
cars.Add(new Car(new ToyotaStrategy(),2011);
Run Code Online (Sandbox Code Playgroud)

这将完全符合您的要求.

但是,您可以在战略和汽车之间找到一种耦合.


解决方案2:使用工厂.

工厂也是一个很好的解决方案,可能更容易.你做的是有一个CarFactory,有多种工厂方法来创建每种类型的汽车.

public class CarFactory{
   public static Car BuildCorvette(int year){
      Car car = new Car(year);
      car.Type = "Corvette;
      car.Speed = 0.9";
      return car;
   }

   public static Car BuildToyota(int year){
      Car car = new Car(year);
      car.Type = "Toyota;
      car.Speed = 0.5";
      return car;
   }
}
Run Code Online (Sandbox Code Playgroud)

用法:

List<Car> cars = new List<Car>();
cars.Add(CarFactory.BuildCorvette(1999));
cars.Add(CarFactory.BuildToyota(2011));
Run Code Online (Sandbox Code Playgroud)

所以关于这一点的好处是你不必担心现在实例化汽车.它全部由CarFactory处理,将您的"实例化逻辑"与您的代码分离.但是,您仍然需要知道要构建哪辆车并相应地调用该方法,这仍然是一个小耦合.


解决方案3:战略工厂!

所以,如果我们想要摆脱最后一点的耦合,让我们将两者结合起来!

public class CarFactory{
   public static Car BuildCar(CarCreationStrategy strategy, int year){
      Car car = new Car(year);
      strategy.BuildCar(car);
      return car;
   }
}

List<Car> cars = new List<Car>();
cars.Add(CarFactory.BuildCar(new CorvetteStrategy(),1999));
cars.Add(CarFactory.BuildCar(new ToyotaStrategy(),2011);
Run Code Online (Sandbox Code Playgroud)

现在你有一个建造汽车的战略,一个为你建造它们的工厂,以及一辆没有你原来的额外联轴器的汽车.很棒,不是吗?

如果您使用过Swing,您会发现这就是他们处理一些事情的方式,比如Layouts(GridBagLayout,GridLayout都是策略).还有一个BorderFactory.


起色

抽象策略

public interface CarCreationStrategy{
   void BuildCar(Car theCar);
}

public class AbstractStrategy:CarCreationStrategy{
   public string Type;
   public double Speed;
   public string Comments;

   public void BuildCar(Car theCar){
       theCar.Type = this.Type;
       theCar.Speed = this.Speed;
       theCar.Comments = this.Comments;
   }
}

public class CorvetteStrategy extends AbstractStrategy{
   public CorvetteStrategy(){
      this.Type = "Corvette";
      this.Speed = 0.9;
      this.Comments = "Speedster!";
   }
}

public class ToyotaStrategy extends AbstractStrategy{
   public ToyotaStrategy{
      this.Type = "Toyota";
      this.Speed = "0.5";
      this.Comments = "Never dies, even if you drop it from the top of a building";
   }
}
Run Code Online (Sandbox Code Playgroud)

使用此功能,您可以灵活地动态创建AbstractStrategies(例如,从数据存储中提取汽车属性).