抽象类的集合(或类似的东西...) [英] A Collection of an Abstract Class (or something like that...)

查看:231
本文介绍了抽象类的集合(或类似的东西...)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景



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



注意:我已经简化了这个场景(尽我所能),使它更一般和更容易理解。我实际上不是在与汽车工作。



我创建了一个 Cars Car 对象的集合。



Car 对象具有速度(双)和(int)。构造函数以年为参数,例如:

  public class Car {
private int year;
私人双倍速度;

public Car(int year){
this.year = year;
}
}

这里是棘手的部分...一种(我们说科尔维特或克隆)。 Corvette将有速度 0.9 ,Clunker将有速度 of 0.1 。 A Car 永远不能实例化,而不指定应该是什么样的汽车。现在,创建一辆汽车,我们有:

  Car car = new Car(1998,Corvette); 

我们刚刚创建的Corvette将是 Car 对象与速度 0.9



问题



我的实际情况涉及更多种类的汽车,除了速度(也许还有 color numDoors fuelTankSize )。有了这么多种汽车(每种都有自己的特定属性),代码变得比我想要的更复杂。



可能的解决方案


  1. 我可以使用子类,也就是说,有一个抽象 Car 类扩展 Corvette Clunker ,但是我有使用 Cars 对象(因为我不能创建一个不能被实例化的东西的集合)。


  2. 使用枚举(例如 CarKind )似乎需要几个乱码开关语句:




    • 填充每个车辆的速度

    • 汽车
    • $创建汽车 b $ b
    • 等。




我正在寻找一个解决方案,允许单个 Cars 类包含每个 Car 对象。我不想要不同的集合(例如 Corvettes Clunkers )。我也在寻找一个解决方案,允许创建 Car 对象基于个人汽车的属性...如前所述,创建一个新的汽车种类 Corvette 会导致速度 0.9 。没有其他方法可以指定汽车的速度



在这种情况下有最佳做法吗?



编辑:我不想要的原因集合的抽象 Car 对象是因为 Cars 集合的点是创建和操作 Car 对象,无论它们的种类。 汽车是抽象的似乎使这复杂化。

解决方案


我在寻找一个解决方案,允许单个Cars类包含
每个Car对象。我不想要不同的集合(如Corvettes,
Clunkers)。我也在寻找一个解决方案,允许创建
基于个人汽车的属性的汽车对象...如前所述的
,创建一个新的汽车科尔维特会导致
在0.9的速度。没有其他方法可以指定汽车的
速度。


哦男孩哦,男孩有这么多种方式处理这一点,我们可以一整天!我会做一个大脑转储,希望它不会太多,你可以处理。






解决方案1:使用策略



策略基本上是一种将重复的可替换逻辑与另一个类分离的方法。在这种情况下,每个汽车都需要不同的创建。一个策略是完美的。



对不起,如果我偶然混合一些C#...自从javaed以来很长时间了。

  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 =永远不会死,即使你从建筑物的顶部掉落;
}
}

现在,

  public class Car {
//变量...

public Car (CarCreationStrategy策略,int年){
strategy.BuildCar(this); //在这里实现您的属性。
this.year = year;
}
}

所以,你现在得到的是如此真棒! / p>

 列表< Car> cars = new List< Car>(); 
cars.Add(new Car(new CorvetteStrategy(),1999));
cars.Add(new Car(new ToyotaStrategy(),2011);






解决方案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;
}
}

用法:

 列表< Car> cars = new List< Car> 
cars.Add(CarFactory.BuildCorvette(1999));
cars.Add(CarFactory.BuildToyota(2011));

所以关于这一点的好处是你不必担心实例化Car现在。它的所有由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);



你有一个建立汽车的战略,一个工厂,为你建立他们,一辆汽车没有从你的原来的额外的联轴器。很好,不是吗?



如果你已经使用了Swing,你会注意到这是他们如何处理像Layouts(GridBagLayout,GridLayout都是策略)等一些东西。还有一个BorderFactory。



< hr>

改进



抽象策略

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

public class AbstractStrategy:CarCreationStrategy {
public string Type;
public double Speed;
public string注释;

public void BuildCar(Car theCar){
theCar.Type = this.Type;
Car.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 =永远不会死,即使你从建筑物的顶部掉落;
}
}

使用它可以灵活地创建AbstractStrategies (例如,从数据存储中提取汽车属性)。


The Scenario

I'm making a program in Java that involves cars.

NOTE: I've simplified this scenario (to the best of my ability) to make it both more general and easier to understand. I'm not actually working with cars.

I've created a Cars class, which is a collection of Car objects.

The Car object has a speed (double) and a year (int). The constructor takes the year as a parameter, for example:

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

    public Car(int year) {
        this.year = year;
    }
}

Here's the tricky part... A car must have a kind (let's say Corvette or Clunker). A Corvette will have a speed of 0.9 and a Clunker will have a speed of 0.1. A Car can never be instantiated without specifying what kind of car it should be. So now, to create a car, we have:

Car car = new Car(1998, Corvette);

The Corvette we've just created will be a Car object with a speed of 0.9.

The Problem

My actual situation involves many more kinds of cars, and each car has several specific attributes besides speed (maybe there are also fields for color, numDoors and fuelTankSize). With so many kinds of cars (each with their own specific attributes), the code is becoming more complex than I'd like.

Possible Solutions

  1. I could work with sub classes, that is, have an abstract Car class that's extended by Corvette and Clunker, but then I have the problem of using a Cars object (because I can't make a collection of something that can't be instantiated). See EDIT below.

  2. Using an enum (such as CarKind) seemingly requires several messy switch statements:

    • to populate the speed field of each car
    • to create Car objects from the Cars class
    • etc.

How You Can Help

I'm looking for a solution that allows a single Cars class to contain every Car object. I don't want different collections (like Corvettes, Clunkers). I'm also looking for a solution that allows the creation of Car objects based on the attributes of an individual car kind... as previously mentioned, creating a new Car of kind Corvette would result in a speed of 0.9. There should be no other way to specify a car's speed.

Is there a best practice in this situation? Have I made the example clear enough?

Thanks.

EDIT: The reason I don't want a collection of abstract Car objects is because the point of the Cars collection is to create and manipulate Car objects, regardless of their kinds. Car being abstract seems to complicate this. If you think this is the best solution, please answer accordingly.

解决方案

I'm looking for a solution that allows a single Cars class to contain every Car object. I don't want different collections (like Corvettes, Clunkers). I'm also looking for a solution that allows the creation of Car objects based on the attributes of an individual car kind... as previously mentioned, creating a new Car of kind Corvette would result in a speed of 0.9. There should be no other way to specify a car's speed.

Oh boy oh boy there are so many ways to deal with this that we could go on all day! I will do a brain dump, and hopefully it will not be too much for you to deal with.


solution 1: use Strategy.

A strategy is basically a way to separate heavy substitutable logic from another class. In this case, every car needs to be created differently. A strategy is PERFECT for this.

Sorry if I mix in some C# by accident... been a long time since I javaed.

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";
   }
}

Now, you can pass a strategy in with your car constructor.

public class Car{
   // Variables ...

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

So, what you get now is so awesome!

List<Car> cars = new List<Car>();
cars.Add(new Car(new CorvetteStrategy(),1999));
cars.Add(new Car(new ToyotaStrategy(),2011);

And this will do exactly what you want.

However, you get a coupling between the strategy and the Car.


solution 2: use Factory.

Factory is an okay solution for this as well, and is probably easier. What you do is have a CarFactory, with multiple factory methods for creating each type of car.

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;
   }
}

Usage:

List<Car> cars = new List<Car>();
cars.Add(CarFactory.BuildCorvette(1999));
cars.Add(CarFactory.BuildToyota(2011));

So the good thing about this is you don't have to worry about instantiating Car now. its all handled by CarFactory, decoupling your "instantiation logic" from your code. However, you still need to know which car you want to build and call that method accordingly, which is still a small coupling.


solution 3: strategy factory!

So, if we wanted to get rid of that last bit of couplings, lets combine the two together!

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);

Now you have a Strategy for building cars, a Factory that builds them for you, and a Car with no extra couplings from your original. Wonderful, isn't it?

If you have worked with Swing, you will notice that this is how they handle a few things like the Layouts (GridBagLayout, GridLayout are all strategies). There's also a BorderFactory as well.


Improvement

Abstract Strategy

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";
   }
}

Using this gives you the flexibility to create AbstractStrategies on the fly (say, pulling car properties from a data store).

这篇关于抽象类的集合(或类似的东西...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆