Sorry if the title doesn't explain the question very well, but I couldn't think any better name. This might end up being a quite long question, but please bear with me.
Let's say I have two types of vehicles Car
and Yacht
which extend an interface called IVehicle
.
The interface itself doesn't matter much for this question, but the classes contain properties describing them.
I then have a ITaxCalculator<T> where T : IVehicle
which contains method double Calculate(T vehicle);
.
There are then several classes which implement different versions of ITaxCalculator<T>
(and take different constructor arguments), such as:
LegitYachtTaxCalculator : ITaxCalculator<Yacht>
TaxHavenYachtTaxCalculator : ITaxCalculator<Yacht>
CarTaxCalculator : ITaxCalculator<Car>
I then have a List<IVehicle>
containing my multiple cars and yachts, and I want to calculate the total amount of taxes I'm going to have to pay for them while at the same time being able to switch out the method used to calculate each type's taxes.
Here's some code:
Interfaces:
ITaxCalculator<T>
public interface ITaxCalculator<T> where T : IVehicle
{
double Calculate(T vehicle);
}
IVehicle
public interface IVehicle
{
string RegistrationPlate { get; }
}
Implementations
Car
public class Car : IVehicle
{
public Car(string registrationPlate)
{
RegistrationPlate = registrationPlate;
}
public string RegistrationPlate { get; }
}
Yacht
public class Yacht : IVehicle
{
public int WeightInTons { get; }
public Yacht(string registrationPlate, int weightInTons)
{
RegistrationPlate = registrationPlate;
WeightInTons = weightInTons;
}
public string RegistrationPlate { get; }
}
CarTaxCalculator : ITaxCalculator<Car>
public class CarTaxCalculator : ITaxCalculator<Car>
{
public double Calculate(Car vehicle)
{
Console.WriteLine($"Calculating tax for {vehicle.GetType().FullName} with plate {vehicle.RegistrationPlate} using {this.GetType().FullName}");
return 4999.95;
}
}
LegitYachtTaxCalculator : ITaxCalculator<Yacht>
public class LegitYachtTaxCalculator : ITaxCalculator<Yacht>
{
public double WeightMultiplier { get; }
public LegitYachtTaxCalculator(double weightMultiplier)
{
WeightMultiplier = weightMultiplier;
}
public double Calculate(Yacht vehicle)
{
Console.WriteLine($"Calculating tax for {vehicle.GetType().FullName} with plate {vehicle.RegistrationPlate} using {this.GetType().FullName}");
return vehicle.WeightInTons * WeightMultiplier;
}
}
TaxHavenYachtTaxCalculator : ITaxCalculator<Yacht>
public class TaxHavenYachtTaxCalculator : ITaxCalculator<Yacht>
{
public double Calculate(Yacht vehicle)
{
Console.WriteLine($"Calculating tax for {vehicle.GetType().FullName} with plate {vehicle.RegistrationPlate} using {this.GetType().FullName}");
return 0.0; // No taxes, woho!
}
}
Main
static void Main(string[] args)
{
List<IVehicle> vehicles = new List<IVehicle>
{
new Car("PLT111"),
new Yacht("PLT333", 2500)
};
double totalTaxes = 0;
foreach (var vehicle in vehicles)
{
//Here I want to use engines which are configurable earlier to calculate the taxes for the vehicles
}
}
I've tried to solve this in many ways such as
- IoC containers
- A much lighter "Resolver" variant where you register engines in a class containing a
Dictionary<Type, object>
whereobject
is ITaxCalculators registered and resolved through methods such aspublic ITaxCalculator<T> GetTaxCalculator<T>() where T : IVehicle
public void RegisterTaxCalculator<T>(ITaxCalculator<T> calculator) where T : IPosition
- Passing the ITaxCalculator to every instance of T during its creation, and letting T calculate its own taxes by using it.
They all end up feeling overly complex, using bad practices or requiring too much boilerplate. So I'm wondering what the best way would be to structure this? Am I on the wrong track from the start, or is there any pattern I haven't thought about yet?
Thanks!
Aucun commentaire:
Enregistrer un commentaire