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

2023-11-27

场景

我正在用 Java 编写一个涉及汽车的程序。

注意:我(尽我所能)简化了这个场景,使其更通用且更容易理解。我实际上并不是在和汽车打交道。

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

The Car对象有一个speed(双)和一个year(整数)。构造函数将年份作为参数,例如:

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

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

这是棘手的部分......汽车必须有一种类型(比如说克尔维特或旧车)。克尔维特将有一个speed of 0.9一个旧车会有一个speed of 0.1. A Car如果不指定它应该是什么类型的汽车,则永远无法实例化。现在,要制造一辆汽车,我们需要:

Car car = new Car(1998, Corvette);

我们刚刚创建的克尔维特将是Car对象具有speed of 0.9.

问题

我的实际情况涉及到的车种类比较多,每辆车除了有几个特定的​​属性speed(也许还有字段color, numDoors and fuelTankSize)。由于汽车种类繁多(每种汽车都有自己的特定属性),代码变得比我想象的更加复杂。

可能的解决方案

  1. 我可以使用子类,即有一个抽象Car扩展的类Corvette and Clunker,但是我遇到了使用的问题Cars对象(因为我无法收集无法实例化的东西)。请参阅下面的编辑。

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

    • 来填充speed每辆车的场
    • 创造Car对象来自Cars class
    • etc.

您可以如何提供帮助

我正在寻找一种解决方案,允许单个Cars类包含每个Car目的。我don't想要不同的收藏(比如Corvettes, Clunkers)。我也在寻找一种允许创建的解决方案Car基于单个汽车类型属性的对象...如前所述,创建一个新的Car同类Corvette会导致speed of 0.9。不应该有其他方法来指定汽车speed.

在这种情况下有最佳实践吗?我举的例子够清楚了吗?

Thanks.

编辑:我不想收集摘要的原因Car对象是因为Cars集合就是创建和操作Car对象,无论其种类如何。Car抽象似乎使事情变得复杂。如果您认为这是最好的解决方案,请相应地回答。


我正在寻找一种解决方案,允许单个 Cars 类包含 每个汽车对象。我不想要不同的收藏(比如克尔维特, 旧车)。我也在寻找一种允许创建的解决方案 基于单个汽车类型属性的汽车对象...如 前面提到过,创造一款类似 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";
   }
}

现在,您可以向汽车构造函数传递策略。

public class Car{
   // Variables ...

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

所以,你现在得到的东西真是太棒了!

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

这将完全满足您的要求。

然而,你会得到策略和汽车之间的耦合。


解决方案2:使用Factory。

Factory 也是一个不错的解决方案,而且可能更容易。您要做的就是拥有一个 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;
   }
}

Usage:

List<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,您会注意到这就是它们处理诸如布局之类的一些事情的方式(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";
   }
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

抽象类的集合(或类似的东西......) 的相关文章

  • 在 Gradle 中运行自定义测试任务而无需重新编译

    我有一个 Gradle 自定义测试任务来运行我的集成测试 我希望能够在 Gradle 不自动完成之前的所有阶段并仅运行测试的情况下运行它 有没有办法在每个构建步骤不使用 x 的情况下执行此操作 None
  • 将 java 方法参数设置为最终参数

    那有什么区别final在下面的代码之间进行 将参数声明为有什么好处final public String changeTimezone Timestamp stamp Timezone fTz Timezone toTz return pu
  • 调试器不会停止在 Intellij IDEA 中的源代码处

    我有一个相当奇怪的问题 无法使用 Intellij IDEA 解决 我正在解析电子邮件文件org apache james mime4j包裹 但我的邮件文件格式不兼容Date 标头 因此 我从 mime4j 源创建了模块 并从磁盘中删除了
  • 在 JList 中写一些东西

    嘿 我还有另一个问题 我创建JList在我的主窗口中 现在我想向其中添加一些内容 我这样做 private void jButton2ActionPerformed java awt event ActionEvent evt Dodaj
  • 如何知道内存中是否已经存在类的实例?

    如何知道内存中是否已经存在类的实例 我的问题是 如果存在类实例 则不想读取方法 这是我的代码 private void jButton java awt event ActionEvent evt PNLSpcMaster pnlSpc n
  • 如何在 Java 中复制对象?

    考虑下面的代码 DummyBean dum new DummyBean dum setDummy foo System out println dum getDummy prints foo DummyBean dumtwo dum Sys
  • bean 的 CDI @TransactionAttribute

    我正在尝试CDI在测试应用程序上 我有一个DAO它注入一个托管的容器JTA像这样的持久化上下文 public class TestDAO implements Serializable PersistenceContext private
  • 如何在 Android 中签署 AAR Artifacts?

    我目前正在开发一个 AAR android 库 我想用我自己的密钥对已发布的工件进行签名 以便我可以确定我是否发布了具有相同名称和功能的假 aar 注意事项1 我希望能够以编程方式检查我的库的真实性 即使是一个伪造的库 只是伪造了我的 aa
  • 如何注册 org.springframework.integration.monitor.IntegrationMBeanExporter

    根据http www ibm com support knowledgecenter en SS7K4U 8 5 5 com ibm websphere nd multiplatform doc ae cspr data access tr
  • 竞争条件和 Clojure Atoms

    clojure atom 的文档指出 Changes to atoms are always free of race conditions 然而 竞争条件不仅是根据更改定义的 而且是在不同线程中并行逻辑操作的上下文中定义的 我想知道 保证
  • 如何防止我的 servlet 被其他网站调用

    好的 我有一个像这样的简单的 servlet public class SimpleServlet extends HttpServlet public void doPost HttpServletRequest req HttpServ
  • Android 的@hide 注解到底有什么作用?

    Android中很多内部API都被标记出来了 hide What exactly这是吗 另一个答案 https stackoverflow com questions 17035271 what does hide mean in the
  • 如何在列表视图中选择时启用视频序列自动播放?

    大家好 有人可以与我分享一下我如何编写我的 viewvideo java 类 以便它允许自动播放视频功能 自动排序在列表视图中播放所选视频的任务 从当前位置到最新录制的视频 按顺序直到最新的视频播放完毕 这类似于 YouTube 自动播放功
  • 如何让 Camel FTP 按需只获取一次

    我对骆驼还很陌生 我一直在尝试让 Camel 根据需要仅通过 FTP 获取单个文件一次 我无法让它发挥作用 这是我尝试过的 让我知道什么是最好的方法以及我的代码有什么问题 1 读取文件后发送一条空消息当收到空消息时 停止路由 from di
  • Java泛型类型参数中的问号是什么意思? [复制]

    这个问题在这里已经有答案了 这是取自斯坦福解析器附带的一些示例的一小段代码 我已经用 Java 进行了大约 4 年的开发 但从未对这种风格的代码应该表示什么有非常深入的理解 List
  • 如何预先填充 JFileChooser 将“文件名”?

    我打算用数据库中的名称填充 JFileChooser 但使用标准 JFileChooser 对话框进行加载 删除 保存和另存为 我想给用户留下这样的印象 他们正在处理文件系统 而在后端使用数据库来保存更改 用户不应该能够浏览到不同的目录进行
  • 原子整数的compareandexchange()与compareandset()

    在研究 AtomicInteger 时 我发现这个 API 提供了两种方法 比较和交换 如果当前值被引用 则自动将该值设置为 newValue to 作为见证值 预期值 记忆效应为 由指定VarHandle compareAndExchan
  • 使用替换但不使用根元素的 Jaxb 继承

    我正在浏览布莱斯的博客http blog bdoughan com 2010 11 jaxb and inheritance using substitution html http blog bdoughan com 2010 11 ja
  • SWT StyledText 有高度限制吗?

    我正在尝试创建一个应用程序 其中包含在 ScrolledComposite 中显示的 StyledText 框 我在 StyledText 框中显示大量行时遇到困难 超过 2 550 行似乎会导致问题 StyledText 框本身不能有滚动
  • 如何将元素添加到通用集合

    我想知道如何将专用对象添加到通用集合中 我正在使用以下代码 Collection

随机推荐