Как избавится от switch case в Asp.Net Core MVC коде?
Всем привет! Делаю калькулятор на Asp.Net Core MVC и у меня получился очень большой Switch Case. Помогите пожалуйста переделать мой код.
Вот мой контроллер:
public class CalcController : Controller
{
public IActionResult IndexCalculator()
{
return View(new CalcModel());
}
[HttpPost]
public async Task<IActionResult> IndexCalculator(CalcModel model)
{
ModelState.Clear();
switch (model.calculationMethod)
{
case CalculationMethod.Addition:
model.Result = model.FirstNumber + model.SecondNumber;
break;
case CalculationMethod.Subtraction:
model.Result = model.FirstNumber - model.SecondNumber;
break;
case CalculationMethod.Multiplication:
model.Result = model.FirstNumber * model.SecondNumber;
break;
case CalculationMethod.Division:
if (model.SecondNumber == 0)
break;
else
model.Result = model.FirstNumber / model.SecondNumber;
break;
case CalculationMethod.X2:
model.Result = Math.Pow(model.FirstNumber, 2);
break;
case CalculationMethod.Sqrt:
model.Result = Math.Sqrt(model.FirstNumber);
break;
case CalculationMethod.Sinsus:
model.Result = Math.Sin((model.FirstNumber * Math.PI) / 180);
break;
case CalculationMethod.Cosinus:
model.Result = Math.Cos((model.FirstNumber * Math.PI) / 180);
break;
case CalculationMethod.Tangens:
model.Result = Math.Tan((model.FirstNumber * Math.PI) / 180);
break;
case CalculationMethod.Cotangens:
model.Result = Math.Sqrt((Math.Cos((model.FirstNumber * Math.PI) / 180)) / (Math.Sin((model.FirstNumber * Math.PI) / 180)));
break;
}
return View(model);
}
}
}
Так же вот моя модель:
namespace MyWeb.Models
{
public class CalcModel
{
[Required(ErrorMessage = "Поле должно быть установлено")]
public double FirstNumber { get; set; }
[Required(ErrorMessage = "Поле должно быть установлено")]
public double SecondNumber { get; set; }
[Required(ErrorMessage = "Поле должно быть установлено")]
public double Result { get; set; }
public CalculationMethod calculationMethod { get; set; }
public enum CalculationMethod
{
Addition = '+',
Subtraction = '-',
Multiplication = '*',
Division = '/',
X2 = 'x',
Sqrt = '√',
Sinsus = 'S',
Cosinus = 'C',
Tangens = 'T',
Cotangens = 'K'
}
}
}
Как сделать мой код лучше?
Ответы (1 шт):
Любое изменение в данном коде приводит к усложнению. Поэтому если "очень большой switch" это единственная проблема, то ничего менять не нужно.
Можно ещё придраться к тому, что добавление новых операций требует изменения метода IndexCalculator. В некоторых случаях это проблема, в других нет.
Чтобы сделать метод `IndexCalculator' закрытым для изменений, примените паттерн команда. То есть вынесите расчет результата каждой операции в отдельный класс: AddCommand, SubtractCommand, MultiplyCommand, и т.д.
Затем объявите глобальную (статическую) переменную типа Dictionary<string, ICalculationCommand>, и заполните его во время загрузки приложения. В Asp.Net Core приложении для этого подойдёт метод Startup.Configure.
Теперь метод IndexCalculator можно упростить до:
[HttpPost]
public async Task<IActionResult> IndexCalculator(CalcModel model)
{
ModelState.Clear();
ICalculationCommand command;
if(!AllCalculationCommands.TryGetValue(model.calculationMethod, out command) {
return BadRequest();
}
model.result = command.Calculate(model.firstNumber, model.secondNumber);
return View(model);
}
Как видите, у этого подхода есть недостаток - каждая операция требует отдельного класса. Это может быть оправдано лишь если вы делаете расширяемый библиотечный модуль. А для реализации данной функции в контроллере вполне годится один большой switch.