Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 停车场OO设计-枚举是否违反开放/关闭原则?_Java_Oop_Object Oriented Analysis - Fatal编程技术网

Java 停车场OO设计-枚举是否违反开放/关闭原则?

Java 停车场OO设计-枚举是否违反开放/关闭原则?,java,oop,object-oriented-analysis,Java,Oop,Object Oriented Analysis,我正在尝试使用面向对象的方法设计一个停车场系统。停车场可设置残疾人、小型、大型、摩托车等多种停车位 最初,我考虑创建一个枚举来对这些不同类型进行建模,如下所示: public enum ParkingSpotType { HANDICAPPED, COMPACT, LARGE, MOTORBIKE } public abstract class ParkingSpot { private ParkingSpotType type; } public class

我正在尝试使用面向对象的方法设计一个停车场系统。停车场可设置残疾人、小型、大型、摩托车等多种停车位

最初,我考虑创建一个枚举来对这些不同类型进行建模,如下所示:

public enum ParkingSpotType {
  HANDICAPPED, 
  COMPACT, 
  LARGE, 
  MOTORBIKE
}
public abstract class ParkingSpot {
    private ParkingSpotType type;
}
public class HandicappedSpot extends ParkingSpot {
}

public class CompactSpot extends ParkingSpot {
}

public class LargeSpot extends ParkingSpot {
}

public class MotorbikeSpot extends ParkingSpot {
}
然后在
ParkingSpot
类中使用这些选项,如下所示:

public enum ParkingSpotType {
  HANDICAPPED, 
  COMPACT, 
  LARGE, 
  MOTORBIKE
}
public abstract class ParkingSpot {
    private ParkingSpotType type;
}
public class HandicappedSpot extends ParkingSpot {
}

public class CompactSpot extends ParkingSpot {
}

public class LargeSpot extends ParkingSpot {
}

public class MotorbikeSpot extends ParkingSpot {
}
类似地,
Vehicle
类也将具有
VehicleType
,这将映射到停车所需的
ParkingSpotType

public class Vehicle {
    private VehicleType vehicleType;
    // other fields 
}

public enum VehicleType {
  CAR (ParkingSpotType.COMPACT), 
  BUS (ParkingSpotType.LARGE), 
  TRUCK (ParkingSpotType.LARGE), 
  BIKE (ParkingSpotType.MOTORBIKE),
  CYCLE (ParkingSpotType.MOTORBIKE);
  
  private ParkingSpotType parkingSpotType;

  VehicleType(ParkingSpotType parkingSpotType) {
      this.parkingSpotType = parkingSpotType;
  }
}
这使我能够通过执行以下操作从
车辆
中查找
驻车档类型

vehicle.getVehicleType().getParkingSpotType()
然而,有人告诉我,这将违反开放/封闭设计原则。任何新类型的添加都可能需要在各种现有位置更改代码,这将违反开放/封闭设计原则,即当需要引入新功能时,不应修改现有的和经过良好测试的类。有人建议我为不同的类型创建不同的子类,如下所示:

public enum ParkingSpotType {
  HANDICAPPED, 
  COMPACT, 
  LARGE, 
  MOTORBIKE
}
public abstract class ParkingSpot {
    private ParkingSpotType type;
}
public class HandicappedSpot extends ParkingSpot {
}

public class CompactSpot extends ParkingSpot {
}

public class LargeSpot extends ParkingSpot {
}

public class MotorbikeSpot extends ParkingSpot {
}

但使用这种方法,如果没有相同的枚举建模,我将如何将车辆映射到ParkingSpot。如果第一种方法确实是糟糕的wrt OO设计,请有人看看并评论一下。如果是,我将如何在第二种方法中解决上述问题?

我不是专家,但我不理解对您的enum解决方案的批评。基于以下几点观察,我认为这很好:

打开/关闭原则允许扩展。这不仅包括创建接口和子类的新实现,还包括在现有类中添加属性和方法——“扩展”和“修改”之间的界限可能看起来很模糊,但据我所知,“打开/关闭”背后的原则是,如果某个客户机、使用者或模块正在使用您的代码库,他们不应该因为您的代码更改而进行重构(在理想情况下)

为此,我不认为向枚举添加新元素与添加扩展ParkingSpot的新类有什么不同。 可能是错的


我想我会问一个例子,如果我们添加了一个新的ParkingSpot枚举元素,当前代码会在哪里中断,但如果我们向ParkingSpot添加了一个新的子类,则不会中断当前代码,因为我目前没有看到任何子类。

我不是专家,但我不理解对您的枚举解决方案的批评。基于以下几点观察,我认为这很好:

打开/关闭原则允许扩展。这不仅包括创建接口和子类的新实现,还包括在现有类中添加属性和方法——“扩展”和“修改”之间的界限可能看起来很模糊,但据我所知,“打开/关闭”背后的原则是,如果某个客户机、使用者或模块正在使用您的代码库,他们不应该因为您的代码更改而进行重构(在理想情况下)

为此,我不认为向枚举添加新元素与添加扩展ParkingSpot的新类有什么不同。 可能是错的

我想我会问一个例子,如果我们添加了一个新的ParkingSpot枚举元素,当前代码会在哪里中断,但如果我们向ParkingSpot添加了一个新的子类,则不会中断,因为我目前没有看到任何子类。

因为问题是“枚举是否违反打开/关闭原则?”我的答案是,由于您无法编写枚举类型的子类,并且枚举类型的用户无法创建自己的实例来满足自己的需求,因此在大多数情况下,这将违反打开/关闭原则,但有两个警告:

  • 如果枚举类型本质上是一个穷举列表(例如,一周中的几天),那么它就不需要“开放扩展”,因为整数不需要“开放扩展”
  • 如果枚举类型的方法在传递满足某些接口(例如排序函数的
    compariable
    )的用户定义类时可能具有不同的行为,则它在该意义上是“开放扩展”的。有关“开放供扩展”不一定意味着允许子类的讨论,请参阅
这就是说,开放/封闭原则在这里有点像是在转移视线,因为您提出的两个备选模型实际上并不是对彼此相同的事物进行建模。您的
ParkingSpotType
enum为一种类型的停车位建模,这样每个enum值都表示停车位的类型;而您的
ParkingSpot
类对一个停车位进行建模,使得该类的一个实例(或其子类的一个实例,例如
MotorbikeSpot
)表示一个单独的停车位,同一子类的多个实例将表示同一类型的不同停车位。考虑:

  • 您可以使用enum
    ParkingSpotTypes
    来表示不同类型的停车位,也可以使用enum
    ParkingSpots
    来表示特定停车场中的实际停车位(如果程序只需要为一个停车场工作,则有一个明确的列表)
  • 您可以使用一个类
    ParkingSpot
    来表示一个实际的停车位,其中包含不同类型停车位的子类,或者您可以使用一个类
    parkingspotype
    ,其实例分别表示一种停车位类型
您选择哪个选项应该取决于您的程序是需要表示实际的停车位,还是仅表示停车位的类型。例如,如果您正在销售只能在车票上指定的停车位使用的停车票,那么您的代码必须知道停车位是什么;如果您正在销售可在车票上指定类型的任何地点使用的停车票,那么您的代码可能只需要知道有多少个地点可用。