在面向对象设计中处理类型指标的最佳方法是什么?

时间:2014-04-29 14:25:32

标签: java oop ooad object-oriented-analysis

我们的商业模式需要识别不同类型的车辆。例如,摩托车,船,游艇,农场设备,雪地车,重型卡车,轻型卡车,乘用车和"其他"。

我认为有两种方法可以处理它:创建一个带有几个子类的Vehicle类,比如船,卡车,汽车,并有一个枚举指示实际类型。这可以工作,允许您表示与公共子类共享一些共同特征的车辆。但是它允许你在类中使用不匹配的枚举。

我认为处理它的传统方法是为每种类型设置一个单独的子类,它可以是车辆的子类或车辆的子类。例如,重型和轻型卡车可能是卡车的子类;船和游艇可能是船的子类;雪地摩托车可能是车辆的子类。问题是,它并不能真正代表其他人的概念。

有没有人对这些场景有任何模式或最佳做法?

彼得

修改 该目的的目的是传达关于车辆的信息并且能够以用户友好的方式显示该信息。例如,从数据库中提取数据并将其显示在要查看/编辑的屏幕上。

这导致了传统OO的另一个缺点,即偏离实际类型的类型指示符,因为它显示了需要执行某种实例的类型并将值转换为用户友好的类型。

(另外,澄清我说的是单个枚举,而不是每个子类的枚举。)

5 个答案:

答案 0 :(得分:6)

我会从一辆车开始,而不是添加太多的抽象 我不会使用类层次结构来描述您可以使用字段来描述的内容。

这些类型的代码是如此不同?

例如,假设您有一种以前没有想过的类型。像水上汽车(这是一辆可以在水上行驶的汽车)或者是一个水上运动车,或者是独轮车。您可以为每种类型创建一个新类,或者您可以使用

等字段完全使用数据驱动它
name: aqua-car
type: Exotic Car
travelsOnWater: true
travelsOdLand: true
wheels: 4

我建议你阅读You Ain't Gonna Need It最好只添加你需要的抽象,而不是你能想象的抽象。

答案 1 :(得分:4)

真实问题

不同的在他们应得自己的班级之前需要做两件“事情”吗?

答案

这完全取决于您将如何使用这些对象。

  • 您会根据他们拥有的某些属性来比较它们(例如,它是否浮动?)?如果是这样,具有差异化属性的单个类是有意义的。
  • 您要在界面上显示您的对象吗?在您的应用程序中,在单个表中显示轻型卡车和重型卡车是否有意义?如果它们不能有意义地存在并显示为一个数据集,那么有两个类是有意义的。

这只是两个例子。关键是,如果您创建一个新类,它应该有用。 Java特别容易过度抽象。


如何处理Other

其他声音就像一群不是卡车而非汽车的车辆。听起来你想要抓住所有其他车辆并将它们放在一个班级中。为什么不使用Vehicle类?不要创建另一个派生自Vehicle的类,但添加零功能。相同的实用性测试适用于此。

  • Vehicle是否足以满足我对所有“其他”车辆的需求?如果没有,我需要创建更多的课程。

我接受了你的建议并创建了两个有用的类。现在,我无法区分他们,我拒绝使用instanceof。我该怎么办?

无论你的课程有多抽象,我总能将你的课程实例添加到List<Object>,然后无法将它们分开。你无法防范你的设计。

让我换一种说法 - 如果您将鸡蛋和汽车添加到列表中,然后您需要区分鸡蛋和汽车,那么您的列表就会出现问题,而不是鸡蛋和汽车。

答案 2 :(得分:2)

您的问题没有简单的答案。因为它依赖于您必须使用该数据结构执行的业务逻辑。

我将从接口Vehicle开始,它将解析Identyficator以获取具体表示的描述。

interface VehicleIdentyficator {
  String identyficator();
}

interface Vehicle {

  Identyficator getIdentyficator();

}

有了这个,你不仅限于课堂,enum或其他类型的设计。

然后我会使用类层次结构来描述每辆车的属性。

之后,在代码中添加一些逻辑/行为方面,看看我的数据结构是否对任务有效。

在一天结束时,重要的方面是执行一些操作。

例如,没有创建三个类卡车,LightTruck和HavyTruck。

您可以创建一个按照他们执行的任务描述它们的类

  • 他们可以在地面上运输
  • 轻型卡车可以承受较少的载荷,但过去常常在小城市旅行。
  • 重型卡车与Light相反。大范围承载更多负载。

当我们比较这艘船时,我们看到船更像是轻型卡车,唯一的区别是它在水上行驶。

因此,尝试理解对象不是它的本质,而是它能做什么。它可以执行哪些任务以及有哪些限制。然后,您的设计将非常接近您的需求。

我希望这句话是正确的,我会重复自己。它接缝你正在使用那些车辆,而不是构建它们。所以要专注于完全填充他们的身体方面的任务。

但你可以做这样的事情

 enum VechicleType implements VehicleIdentyficator {
   TRUCK("TRUCK"),
   HEAVY_TRUCK("HEAVY_TRUCK")

   private final String indentyficator;

   private VechicleType(String indetyficator) {
     this.indentyficator = identyficator;
   }

   public String identyficator() {
       return indentyficator; 
   }

 }

但是每次添加一些新车时,必须覆盖使用这种新硬编码类型的所有点。

答案 3 :(得分:0)

正如其他人所说,我认为这取决于你将如何使用你的车辆。

  • 如果您只是需要在某些点区分类型,但是您大多以相同的方式处理所有车辆,请选择枚举类型。

  • 如果您确实需要指定不同的行为并使用共享功能/行为,请转到完整的类层次结构。这也是我的首选方法,因为我觉得它提供了更多的进化性。

答案 4 :(得分:0)

在OO开发中处理类型指标的最佳方法是没有类型指标。 类型指标是结构化编程 (那就是认为早于面向对象编程)的概念。 在OO中,类型由类型识别,而不是由人工指示符识别。

编辑:

如果你有一个固定的领域,你必须用一个物体代表(例如:拖拉机,快艇,划艇,摩托车,马自达626,皮卡车,半卡车)然后你可以(也许应该)用具体的类来表示每件事。有趣的设计问题将基于您对对象的需求。

如果你只是需要知道&#34;这是一辆水车&#34;或者&#34;这有多少轮子&#34;然后使用具有isWaterVehicle()getWheelCount()isTruck()方法的接口。在对象上实现接口并对答案进行硬编码。例如:

class SpeedBoat implements VehicleInfo
{
    public int getWheelCount()
    {
        return 0;
    }

    public boolean isTruck()
    {
       return false;
    }

    public boolean isWaterVehicle()
    {
       return true;
    }
}

如果您有大量类似的对象,请使用抽象类来设置默认值。

abstract class AbstractTruck implements VehicleInfo
{
    public final int isTruck()
    {
        return true;
    }
}