Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // https://youtu.be/vTnlFdRf1Kc
- var martinFowler = new Person(10, "Martin Fowler);
- var server = new DemoDiscountServer(person);
- var book = new Book("Design Patern", new List<Person>{martinFowler});
- var discountApplications = server.GetDiscountAmounts(10, new DiscountContext(book))
- public interface IDiscount
- {
- IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context);
- }
- public record DiscountApplication(string Label, Money amount);
- public record Book(string Title, List<Person> Authors);
- public record DiscountContext(Book? book);
- public record Person(int Id, string Name);
- public class DemoDiscountServer : IDiscountServer
- {
- private readonly Person _martinFowler;
- public DemoDiscountServer(Person author) => _martinFowler = author);
- public IDiscount GetDiscounts() =>
- GetPatternBooksDiscount(.30M).WhenBookAuthorBy(_martinFowler)
- .OrElse(GetPatternBooksDiscount(.20M))
- .OrElse(new RelativeDiscount(.10M).WhenPositivePrice().OnAllBooks());
- private Discount GetPatternBooksDiscount(decimal factor) =>
- new RelativeDiscount(factor).WhenPositivePrice().WhenTitleContains("pattern");
- }
- public static class DiscountExtensions
- {
- public static IDiscount WhenBookAuthorBy(this IDiscount discount, Person author)
- {
- return new BookAuthorDiscount(person, discount)
- }
- public static IDiscount WhenPositivePrice(this IDiscount discount) // relativeDiscount
- {
- return new PositivePriceDiscount(discount)
- }
- public static IDiscount WhenTitleContains(this IDiscount discount, string pattern) // relativeDiscount
- {
- // the registration is done is this order
- // RelativeDiscount => PositivePriceDiscount => TitleContentDiscount
- // the call will be done in this order
- // RelativeDiscount <= PositivePriceDiscount <= TitleContentDiscount
- return new TitleContentDiscount(pattner, discount) //
- }
- public static IDiscount GetPatternBook(this IDiscount)
- {
- return new RelativeDiscount(factory).WhenPositivePrice().WhenTitleContains("pattern");
- }
- public static Discount OrElse(this IDiscount discount, IDiscount elseDiscount)
- {
- // TODO:
- // has to return something that will be a ElseDiscount which will call its
- // GetDiscountAmounts(..) if `discount`.GetDiscountAmounts return empty set
- return elseDiscount;
- }
- public static Enumerable<DiscountApplication> OnAllBooks(IDiscount discount) // PositivePriceDiscount
- {
- return discount.GetDiscountAmounts().WithSuffix(" on all books)";
- }
- }
- internal static class DisocuntApplicationExtensions
- {
- internal static IEnumerable<DiscountApplication> WithSuffix(this IEnumerable<DiscountApplication> discounts, string suffix)
- {
- return discounts.Select(discount => discount with {Label = discount.Label + suffix});
- }
- }
- public class RelativeDiscount : IDiscount
- {
- public RelativeDiscountd(decimal factor) => _factor = factory > 0 && factor < 1 ? factory
- : throw new ArgumentException("Multiplying factor must be positive and smaller than 1.");
- public IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context) =>
- price == Money.Zero ? Enumerable.Empty<DisocuntApplication>() // can remove?
- : new[] { new DiscountApplication($"{_factor:P2} discount", price * _factor) };
- }
- public abstract class RestrictedDiscount : IDiscount
- {
- private readonly IDiscount _other;
- private readonly string _labelSuffix;
- protected RestrictedDiscount(IDiscount other, string labelSuffix) => (_other, _labelSuffix) => (other, labelSuffix);
- public IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context) =>
- AppliesTo(context) ? ApplyTo(price, context).WithSuffix(_labelSuffix)
- : IEnumerable.Empty<DiscountApplication>();
- protected IEnumerable<DiscountApplication> ApplyTo(Money price, DiscountContext context) =>
- _other.GetDiscountAmounts(price, context);
- protected abstract bool AppliesTo(DiscountContext context);
- }
- public class NoDiscount : IDiscount
- {
- public IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context) =>
- Enumerable.Empty<DiscountAppliction>();
- }
- public class ElseDiscount : IDiscount
- {
- private readonly IDiscount _ifDiscount;
- private readonly IDiscount _elseDicount;
- ElseDiscount(IDiscount ifDiscount, IDiscount elseDiscount) => (_ifDiscount, _elseDicount) = (ifDiscount, elseDiscount)
- public IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context)
- {
- // NOTE: I suspect this is the implementation
- var appDiscounts = ifDiscount.GetDiscountAmounts(price, context).ToList();
- appDiscounts.Count > 0 ? appDiscounts : elseDiscount.GetDiscountAmounts(price, context);
- }
- }
- public class TitleContentDiscount : RestrictedDiscount
- {
- private readonly IDiscount _other;
- public BookAuthorDiscount(string titleSubstring, IDiscount other)
- :base(other, $" when by '{titleSubstring}' in the title") => _titleSubstring != string.IsNullOrEmpty(titleString) ? titleString
- : throw new ArgumentException("....");
- protected override bool AppliesTo(DiscountContext context) =>
- context.Book?.Title.Contains(_titleSubstring, StringComparison.InvariantCultureIgnoreCase) ?? false;
- }
- public class BookAuthorDiscount : RestrictedDiscount
- {
- private readonly IDiscount _other;
- public BookAuthorDiscount(Person author, IDiscount other)
- :base(other, $" authored by {author.FullName}") => _author = author;
- protected override bool AppliesTo(DiscountContext context) =>
- context.Book?.Authors.Any(author => author.Id => _author.Id) ?? false;
- }
- public class PositivePriceDiscount : IDiscount
- {
- private readonly IDiscount _other;
- public PositivePriceDiscount(IDiscount other) => _other = other;
- public IEnumerable<DiscountApplication> GetDiscountAmounts(Money price, DiscountContext context) =>
- price == Money.Zero ? Enumerable.Empty<DisocuntApplication>()
- : _other.GetDiscountAmounts(price, context);
- }
- Follow on github
- https://github.com/ivandrofly
- https://x.com/ivandrofly
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement