На данный момент ваше решение кажется приемлемым, однако я бы предпочел, чтобы вы разработали какую-то политику правил, чтобы ваше бронирование на самом деле не заботилось о том, как оно оплачивается, а скорее, чтобы правила определялись вариантом использования (вы будетеобратите внимание, что это решение на самом деле также технически основано на шаблоне стратегии).
Например, предположим, у вас есть класс Театра, для которого вы бронируете билеты.В этом классе театра используется следующий метод:
public PaymentResult MakeReservation(IPaymentPolicy paymentPolicy, int itemsToBuy)
{
var result = paymentPolicy.Verify(itemsToBuy);
if(result.HasFailingRules)
{
return result;
}
// Do your booking here.
}
Здесь объект театра отвечает за одно решение - разрешено ли бронирование с учетом предоставленных мне правил?Если да, тогда сделайте заказ, в противном случае сообщите об ошибках.
Тогда вызывающий абонент сможет контролировать правила в зависимости от варианта использования.Например:
public void MakePaypalReservation(int itemsToBuy)
{
var rulesPolicy = new PaymentRulesPolicy(
new MaxItemsRule(10),
new MaxAmountRule(10000)
);
var theatre = this.repo.Load("Theatre A"); // Load by id
var paymentResult = theatre.MakeReservation(rulesPolicy, itemsToBuy);
// Here you can use the result for logging or return to the GUI or proceed with the next step if no errors are present.
}
public void MakeCashReservation(int itemsToBuy)
{
var rulesPolicy = new PaymentRulesPolicy(
new MaxItemsRule(2),
new MaxAmountRule(100),
new TimeOfDayRule(8, 20) //Can only buy between 8 in the morning at 8 at night as an example.
);
var theatre = this.repo.Load("Theatre A"); // Load by id
var paymentResult = theatre.MakeReservation(rulesPolicy, itemsToBuy);
// Here you can use the result for logging or return to the GUI or proceed with the next step if no errors are present.
}
Предположим, что у PaymentRulesPolicy имеется конструктор с такой сигнатурой:
public PaymentRulesPolicy(params IRule[] rules);
У вас есть метод для каждого варианта использования.Если вы можете оплатить другим способом, например, ваучером, вы можете создать новую политику с некоторыми новыми правилами.
Конечно, вам также нужно будет предоставить объекту театра всю информацию, необходимую для бронирования.,Метод Verify () политики правил, скорее всего, примет все эти фрагменты информации и передаст минимально необходимую информацию отдельным правилам.
Вот пример того, как может выглядеть политика правил:
public class PaymentRulesPolicy
{
private readonly IRule[] rules;
public PaymentRulesPolicy(params IRule[] rules)
{
this.rules = rules;
}
public PaymentResult Verify(int numItemsToBuy, DateTime bookingDate)
{
var result = new PaymentResult();
foreach(var rule in this.rules)
{
result.Append(rule.Verify(numItemsToBuy, bookingDate);
}
return result;
}
}
Это уже плохой интерфейс, так как все правила требуют всю информацию, независимо от того, что она проверяет.Если это выходит из-под контроля, вы можете улучшить его, передав информацию о бронировании при первом создании политики:
var rulesPolicy = new PaymentRulesPolicy(
new MaxItemsRule(2, itemsToBuy),
new MaxAmountRule(100, itemsToBuy, costPerItem),
new TimeOfDayRule(8, 20, currentDateTime)
);
В конце дня преимущество этого шаблона состоит в том, что все ваши деловые решения принимаютсязаключены в один класс каждый, что делает его чрезвычайно простым в обслуживании.Надеемся, что просто рассмотрение конструкции этих политик даст вам хороший обзор того, что они будут применять.Затем вы можете составить эти правила в большую политику.
Другим преимуществом этого подхода также будет модульное тестирование.Вы можете очень легко проверить правила в изоляции.Можно даже создать фабрику для правил и проверить, что фабрика создает правильную политику с правильными правилами для каждого варианта использования и т. Д.
Помните, что это только одно из многих возможных решений, и это конкретное решение можетбыть чрезмерным для вашего приложения или, возможно, оно не соответствует шаблонам, с которыми вы и ваша команда знакомы.Экспериментируя со своим решением о наследовании, вы можете обнаружить, что его достаточно или даже проще понять, учитывая привычки и опыт вашей команды.