public static class Program
public static void Main(string[] args)
var dm = new DiscountManager(new DefaultAccountDiscountCalculatorFactory(), new DefaultLoyaltyDiscountCalculator());
var newPrice = dm.ApplyDiscount(price, AccountStatus.MostValuableCustomer, 10);
Console.WriteLine(newPrice);
var dm2 = new DiscountManager(new DefaultAccountDiscountCalculatorFactory(), new SpecialLoyaltyDiscountCalculator());
var newPrice2 = dm2.ApplyDiscount(price, AccountStatus.MostValuableCustomer, 10);
Console.WriteLine(newPrice2);
public class DiscountManager
private readonly IAccountDiscountCalculatorFactory _factory;
private readonly ILoyaltyDiscountCalculator _loyaltyDiscountCalculator;
public DiscountManager(IAccountDiscountCalculatorFactory factory, ILoyaltyDiscountCalculator loyaltyDiscountCalculator)
_loyaltyDiscountCalculator = loyaltyDiscountCalculator;
public decimal ApplyDiscount(decimal price, AccountStatus accountStatus, int timeOfHavingAccountInYears)
decimal priceAfterDiscount = 0;
priceAfterDiscount = _factory.GetAccountDiscountCalculator(accountStatus).ApplyDiscount(price);
priceAfterDiscount = _loyaltyDiscountCalculator.ApplyDiscount(priceAfterDiscount, timeOfHavingAccountInYears);
return priceAfterDiscount;
public interface ILoyaltyDiscountCalculator
decimal ApplyDiscount(decimal price, int timeOfHavingAccountInYears);
public class DefaultLoyaltyDiscountCalculator : ILoyaltyDiscountCalculator
public decimal ApplyDiscount(decimal price, int timeOfHavingAccountInYears)
decimal discountForLoyaltyInPercentage = (timeOfHavingAccountInYears > Constants.MAXIMUM_DISCOUNT_FOR_LOYALTY) ? (decimal)Constants.MAXIMUM_DISCOUNT_FOR_LOYALTY/100 : (decimal)timeOfHavingAccountInYears/100;
return price - (discountForLoyaltyInPercentage * price);
public class SpecialLoyaltyDiscountCalculator : ILoyaltyDiscountCalculator
public decimal ApplyDiscount(decimal price, int timeOfHavingAccountInYears)
decimal discountForSpecialLoyaltyInPercentage = (timeOfHavingAccountInYears > Constants.MAXIMUM_DISCOUNT_FOR_SPECIAL_LOYALTY) ? (decimal)Constants.MAXIMUM_DISCOUNT_FOR_SPECIAL_LOYALTY/100 : (decimal)timeOfHavingAccountInYears/100;
return price - (discountForSpecialLoyaltyInPercentage * price);
public interface IAccountDiscountCalculatorFactory
IAccountDiscountCalculator GetAccountDiscountCalculator(AccountStatus accountStatus);
public class DefaultAccountDiscountCalculatorFactory : IAccountDiscountCalculatorFactory
public IAccountDiscountCalculator GetAccountDiscountCalculator(AccountStatus accountStatus)
IAccountDiscountCalculator calculator;
case AccountStatus.NotRegistered:
calculator = new NotRegisteredDiscountCalculator();
case AccountStatus.SimpleCustomer:
calculator = new SimpleCustomerDiscountCalculator();
case AccountStatus.ValuableCustomer:
calculator = new ValuableCustomerDiscountCalculator();
case AccountStatus.MostValuableCustomer:
calculator = new MostValuableCustomerDiscountCalculator();
throw new NotImplementedException();
public interface IAccountDiscountCalculator
decimal ApplyDiscount(decimal price);
public class NotRegisteredDiscountCalculator : IAccountDiscountCalculator
public decimal ApplyDiscount(decimal price)
public class SimpleCustomerDiscountCalculator : IAccountDiscountCalculator
public decimal ApplyDiscount(decimal price)
return price - (Constants.DISCOUNT_FOR_SIMPLE_CUSTOMERS * price);
public class ValuableCustomerDiscountCalculator : IAccountDiscountCalculator
public decimal ApplyDiscount(decimal price)
return price - (Constants.DISCOUNT_FOR_VALUABLE_CUSTOMERS * price);
public class MostValuableCustomerDiscountCalculator : IAccountDiscountCalculator
public decimal ApplyDiscount(decimal price)
return price - (Constants.DISCOUNT_FOR_MOST_VALUABLE_CUSTOMERS * price);
public static class PriceExtensions
public static decimal ApplyDiscountForAccountStatus(this decimal price, decimal discountSize)
return price - (discountSize * price);
public static decimal ApplyDiscountForTimeOfHavingAccount(this decimal price, int timeOfHavingAccountInYears)
decimal discountForLoyaltyInPercentage = (timeOfHavingAccountInYears > Constants.MAXIMUM_DISCOUNT_FOR_LOYALTY) ? (decimal)Constants.MAXIMUM_DISCOUNT_FOR_LOYALTY/100 : (decimal)timeOfHavingAccountInYears/100;
return price - (discountForLoyaltyInPercentage * price);
public static class Constants
public const int MAXIMUM_DISCOUNT_FOR_LOYALTY = 5;
public const decimal DISCOUNT_FOR_SIMPLE_CUSTOMERS = 0.1m;
public const decimal DISCOUNT_FOR_VALUABLE_CUSTOMERS = 0.3m;
public const decimal DISCOUNT_FOR_MOST_VALUABLE_CUSTOMERS = 0.5m;
public const decimal MAXIMUM_DISCOUNT_FOR_SPECIAL_LOYALTY = 10;
public enum AccountStatus