I have a class Vehicles with three list fields, namely:
turboVehicles : List<ITurboVehicle>,
trailerVehicle : List<ITrailerVehicle>,
vehicles : List<IVehicle>
, (containing all vehicles from lists 1 and 2 and more)where both ITurboVehicle
and ITrailerVehicle
extends IVehicle
.
I want this class to be able to move all vehicles at the same time, and also be able to gas()
, brake()
them all at the same time as well. The thing is that ITurboVehicle
and ITrailerVehicle
are subinterfaces to IVehicle
, and have further functionality that I want this class to be able to trigger, like turboOn()
and Off.
Main question:
What is a good way of modeling these lists of vehicles for appropriate use in client code? I want to hide as much complexity as possible and keep it organized well in an OO sense. The vehicles
and trailerVehicles
lists are both updated whenever addTrailerTruck(TrailerVehicle tv)
is used for example, to distinguish between them when sub-class specific methods are used. I know that the visitor pattern could have been a good choice to achieve some of the functionality that I have been looking for, but I want to try and find other solutions.
Less important, side-stepping question:
The following has more to do with the general structure I have been trying out to make the Vehicles
class easy and intuative to use: I have been trying to use the composite design pattern, but it seems like the composite class has to be of the same type as the components, which has gotten me stuck sort of. Are there any ways to use the composite pattern and still be able to access all the sub-class functionality?
In my view, it is better to have just one class which manages of state of all vehicles. After doing this, your classes will correspond to the single responsibility principle of SOLID. Read more about single responsibility principle of SOLID here
Let me show an example:
public interface IVehicle
{
void Gas();
void Brake();
}
public interface ITurboVehicle : IVehicle
{ }
public interface ITrailerVehicle : IVehicle
{ }
and concrete implementation of vehicle:
public class TrailerVehicle : ITrailerVehicle
{
public void Brake()
{
throw new NotImplementedException();
}
public void Gas()
{
throw new NotImplementedException();
}
}
And vehicle manager class:
public class VehicleManager
{
public List<IVehicle> Vehicles { get; set; } = new List<IVehicle>();
public void AddTrailer(ITrailerVehicle trailerVehicle)
{
Vehicles.Add(trailerVehicle);
}
public void GasAll()
{
foreach (IVehicle vehicle in Vehicles)
vehicle.Gas();
}
}