Извините, если название не очень хорошо объясняет вопрос, но я не могу придумать лучшего названия. Это может оказаться довольно длинным вопросом, но, пожалуйста, потерпите меня.
Допустим, у меня есть два типа транспортных средств Car
и Yacht
, которые расширяют интерфейс под названием IVehicle
.
Сам интерфейс не имеет большого значения для этого вопроса, но классы содержат свойства, описывающие их.
У меня тогда есть ITaxCalculator<T> where T : IVehicle
, который содержит метод double Calculate(T vehicle);
.
Затем существует несколько классов, которые реализуют разные версии ITaxCalculator<T>
(и принимают разные аргументы конструктора), такие как:
LegitYachtTaxCalculator : ITaxCalculator<Yacht>
TaxHavenYachtTaxCalculator : ITaxCalculator<Yacht>
CarTaxCalculator : ITaxCalculator<Car>
Затем у меня есть List<IVehicle>
, содержащее мои несколько машин и яхт, и я хочу рассчитать общую сумму налогов, которые мне придется заплатить за них, и в то же время иметь возможность переключаться на используемый метод. рассчитать налоги каждого типа.
Вот код:
Интерфейсы:
ITaxCalculator<T>
public interface ITaxCalculator<T> where T : IVehicle
{
double Calculate(T vehicle);
}
IVehicle
public interface IVehicle
{
string RegistrationPlate { get; }
}
Реализация
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!
}
}
Главная
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
}
}
Я пытался решить эту проблему разными способами, например
- Контейнеры IoC
- Гораздо более легкий вариант "Resolver", где вы регистрируете движки в классе, содержащем
Dictionary<Type, object>
, где object
- это ITaxCalculators, зарегистрированные и разрешенные с помощью таких методов, как
public ITaxCalculator<T> GetTaxCalculator<T>() where T : IVehicle
public void RegisterTaxCalculator<T>(ITaxCalculator<T> calculator) where T : IPosition
- Передача ITaxCalculator каждому экземпляру T во время его создания и возможность использования T для расчета собственных налогов.
Все они в конечном итоге чувствуют себя чрезмерно сложными, применяя плохие методы или требуя слишком много шаблонов. Поэтому мне интересно, как лучше всего это структурировать? Я ошибаюсь с самого начала или есть какой-то паттерн, о котором я еще не думал?
Спасибо! * * 1092