2

I am reading about OOD and came across Parking lot design problem.Parking lot has parking floors which has parking spots.The parking spot class looks as follow:

public enum ParkingSpotType {
  HANDICAPPED, COMPACT, LARGE, MOTORBIKE, ELECTRIC
}
public abstract class ParkingSpot {
  private String number;
  private boolean free;
  private Vehicle vehicle;
  private final ParkingSpotType type;

  public boolean IsFree();

  public ParkingSpot(ParkingSpotType type) {
    this.type = type;
  }

  public boolean assignVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
    free = false;
  }

  public boolean removeVehicle() {
    this.vehicle = null;
    free = true;
  }
}

public class HandicappedSpot extends ParkingSpot {
  public HandicappedSpot() {
    super(ParkingSpotType.HANDICAPPED);
  }
}

public class CompactSpot extends ParkingSpot {
  public CompactSpot() {
    super(ParkingSpotType.COMPACT);
  }
}

public class LargeSpot extends ParkingSpot {
  public LargeSpot() {
    super(ParkingSpotType.LARGE);
  }
}

public class MotorbikeSpot extends ParkingSpot {
  public MotorbikeSpot() {
    super(ParkingSpotType.MOTORBIKE);
  }
}

public class ElectricSpot extends ParkingSpot {
  public ElectricSpot() {
    super(ParkingSpotType.ELECTRIC);
  }
}

The parameters are self explanatory.So here why do we need separate classes for each ENUM value?What is the advantage of this?I thought of having only one ParkingSpot class type with one field representing type of parking slot.But why do we need to have separate classes for each ENUM value along with storing Enum as a field also?

Note: For complete design please refer https://www.educative.io/courses/grokking-the-object-oriented-design-interview/gxM3gRxmr8Z

1
  • 2
    You're absolutely right - there is no benefit to the additional classes in this scenario because each derived class differs only by the data or state stored in its member fields, and does not differ in its shape or behaviour. In fact, this could even be considered a code smell on the basis that specifying an Enum value as well a class to both represent the same thing appears to violate the DRY Principle – Ben Cottrell Sep 27 '20 at 7:17
3

You are correct that right now the derived classes are superfluous, because their only difference is one specific enum value, which is labeled the exact same way. You could omit either the enum or the derived classes, and nothing would change.

However, that conclusion might change when there are more differences than just the enum value.

For example, if the price of the parking spot is calculated differently based on which type of spot it is. By having the derived classes, you can keep each parking spot type's calculation logic separately and have them override the same base method.
Comparatively, if you only had the base class to work with, it'd have to contain all of the calculation logic.

However, the current example is a bit light on context and list of future features to decide whether the inheritance is warranted here or not. We shouldn't only evaluate the current state of the code (in which your observation is correct), but also account for any changes that are planned/expected in the near future.


That being said, I suspect that you're generally going to end up either having to remove the derived classes or the enum. I don't see the benefit of implementing the same information in two different ways.

0

The difference becomes apparent if we consider

CompactSpot.Assign(Car.SUV)

this should obviously produce an error of some kind and we have two choices about how to implement it.

either:

ParkingSpot.Assign(car)
{
    if(car is SUV && this.type = COMPACT)
    {
        throw CarTooLarge()
    }
    if(car != HANDICAPPED && this.type == HANDICAPPED)
    ....
}

CompactSpot : ParkingSpot
    Assign(car)
    {
        if(car is SUV)
        {
            throw CarTooLarge()
        }
        base.assign(car);
    }
}

The Inheritance approach allows us to divide the conditional logic between multiple classes rather than having a large conditional block and logic in the base class.

If I consume your ParkingSpot class as a binary dll, I can inherit a new type of ParkingSpot and add my own logic. Which I can't do if you have an enum

3
  • But there must be some service let us say ParkingAllocator that will first look for a relevant free slot for a given vehicle and only if a free slot of a particular vehicle is available,we will park a vehicle there.So if we are trying to assign a vehicle to a spot ,we are absolutely sure that the spot is large enough for vechile. Does this make sense? – rahul sharma Sep 27 '20 at 11:22
  • no. either way you have an if block vs inheritance – Ewan Sep 27 '20 at 11:49
  • Why if block?While i am assigning slots to vehicles,i will search for compatible slot and assign vehicle to it.I am sure that my system will run into CarTooLarge exception. – rahul sharma Sep 27 '20 at 14:01
0

The question answers itself if we think about behavior instead of state, and we should. Inheritance is motivated by "doing the same thing, but differently" or having additional functionality for various subtypes. Perhaps the designers have a good notion that ParkingSpot and Vehicle behavior will expand and evolve. Maybe for the sake of learning they simply baked in sub-typing.

While an ENUM will differentiate same-type vehicles/parkingSpots the requirements for functionality should be an overriding consideration. Even so, an enum may still be appropriate.

There is a need to match vehicles and parking spots - that it is an ENUM is merely an implementation detail. So a VehicleType pubic property seems to fit. This property is much more in the spirit of OO than, say, the client code rummaging thru Reflection / metadata. Client code should not calculate state of another object.


But there must be some service let us say ParkingAllocator that will first look for a relevant free slot for a given vehicle and only if a free slot of a particular vehicle is available, we will park a vehicle there.So if we are trying to assign a vehicle to a spot ,we are absolutely sure that the spot is large enough for vehicle. Does this make sense?

The use case diagram shows parking attendant and customer actors. They're not on the class diagram but they are part of the problem space.


I think there are missing or defective requirements.

  • Is a smaller vehicle allowed in a larger slot? Motorcycles fit everywhere.

  • Any given vehicle object could be electric or have handicap permissions or both - in real life anyway - so I see ElectricSlot & HandicapSlot as attributes of a parking spot. As shown, the class diagram here is inconsistent with the concept of different size vehicles fitting in different size slots.

  • There is no apparent match between parking spot types and vehicle types. Which vehicle(s) require "large", for example? Off hand, a Dictionary can explicitly match spots to vehicles, and/or vice versa. Also underlying enum integer values can represent relative parking spot size. And as I said above, "electric" is not a size.


Data Structures!

this stuff ...

if(car is SUV)
    {
        throw CarTooLarge()
    }
    base.assign(car);
}

goes away if this vehicle-type/spot-type matching is a data structure. A Dictionary is a data structure. Off hand, I see two dictionaries - vehicle->spot and spot->vehicle - as the core of a class with appropriate methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.