What's the best way to handle type indicators in object-oriented design? [duplicate]

為{幸葍}努か 提交于 2019-12-05 09:32:22

The Real Question

How different do two "things" need to be before they deserve their own class?

The Answer

It depends entirely on how you are going to use the objects.

  • Will you be comparing them based on some property they have (e.g., does it float?)? If so, a single class with a differentiating property makes sense.
  • Are you going to display your objects on an interface? Would it make sense within your application to display Light Trucks and Heavy Trucks in a single table? If they cannot meaningfully exist and be displayed as one data set, then it makes sense to have two classes.

Those are just two examples. The point is, if you create a new class, it should be useful. Java is particularly prone to over-abstraction.


What do I do about Other?

Other sounds like a group of Vehicles that are not Trucks and not Cars. It sounds like you want to catch all other Vehicles and put them in one class. Why not use the Vehicle class? Don't create another class that derives from Vehicle but adds zero functionality. The same usefulness test applies here.

  • Is a Vehicle useful enough to satisfy my needs for all "other" vehicles? If not, I need to create more classes.

I took your advice and created two useful classes. Now, I can't tell them apart and I refuse to use instanceof. What do I do?

No matter how abstracted your classes are, I will always be able to add instances your class to a List<Object> and will then be unable to tell them apart. You cannot bulletproof your design.

Let me put it another way - if you add Eggs and Cars to a List, and you later need to differentiate between Eggs and Cars, then there is a problem with your List, not the Eggs and Cars.

I would start with a Vehicle and not add too much abstraction.
I wouldn't use the class hierarchy to describe something you could use a field to describe.

Is the code for these types so different?

For example, say you have a type you didn't think of before. like an aqua-car (which is a car which can travel over water) or a seyway, or a unicycle. You could create a new class for each type or you could have it entirely data driven with fields like

name: aqua-car
type: Exotic Car
travelsOnWater: true
travelsOdLand: true
wheels: 4

I suggest you read You Ain't Gonna Need It Better to add only the abstraction you need, not the abstraction you can imagine.

There is not simple answer for your question. Because its depend on the business logic you will have to perform with that data structure.

I would start with an interface Vehicle that will resolve a Identyficator from to get the description of concrete representant.

interface VehicleIdentyficator {
  String identyficator();
}

interface Vehicle {

  Identyficator getIdentyficator();

}

With this you are not limited to class, enum or other kind of design.

Then i would use class hierarchy to describe the properties of each vehicle.

After that add some logic/behavioural aspects to the code and get a look that my data structures are valid for the task.

At the end of the day the important aspect is to perform some operations.

For example there is no point of creation three classes Truck, LightTruck and HavyTruck.

You could create a class that describe them by task they perform

  • They can transport on ground
  • The Light truck can carry less load but it used to travel in small cities.
  • The Heavy truck is opposite to Light. Have big Range carry more load.

When we compare to this a boat we see that boat is more like light truck the only difference is that it travel on water.

So try to understand the object not be what it is but what it can do. What tasks can be performed by it and what are the limitation. Then with your design will be really close to what you need.

I hope this sentence is correct and i will repeat myself. It seams that you are using those vehicles, not constructing them. So focus on their mission to full fill not on their physical aspects.

But you can do something like this

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

 }

But then every time you add some new vehicle you must cover all points where such new hard coded type will be used.

As others stated, I think it depends on how you're gonna use your vehicles.

  • If you just need to distinguish between types at some points, but you mostly handle all vehicles the same way, go for the enum type.

  • If you really need to specify different behaviors and you make use of shared features/behaviors, go for a full class hierarchy. That's also my preferred approach, because I feel like it offers more evolutivity.

The best way to handle type indicators in OO development is to not have type indicators. Type indicators are a structured programming (that think that predates object oriented programming) concept. In OO, type is identified by type, not by an artificial indicator.

Edit:

If you have a fixed domain of things that you must represent with an object (for example: tractor, speed boat, row boat, motorcycle, mazda 626, pickup truck, deuce-and-a-half truck) then you can (perhaps should) represent each thing with a concrete class. The interesting design question will be based on what you need to do with the objects.

If you just need to know "is this a water vehicle" or "how many wheels does this have" then use an Interface with isWaterVehicle(), getWheelCount(), isTruck() methods. Implement the interface on your objects and hard code the answer. For example:

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

    public boolean isTruck()
    {
       return false;
    }

    public boolean isWaterVehicle()
    {
       return true;
    }
}

If you have a large number of similar objects, use an abstract class to set the defaults.

abstract class AbstractTruck implements VehicleInfo
{
    public final int isTruck()
    {
        return true;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!