dimanche 22 mars 2020

Implementing factory pattern on a shopping cart

I have a task where I need to implement a basic shopping cart system. In this shopping cart, there will be different type of campaigns which is applicable to category of products. These campaigns is going to apply different kind of discounts. To achieve this, I decided to implement the factory pattern.

Lets start with the base class for all discount types;

public abstract class Discount
{
    public Category Category { get; set; }
    public int MinimumItems { get; set; }

    public Discount(Category category, int minItems)
    {
        Category = category;
        MinimumItems = minItems;
    }
}  

The campaign interface;

public interface ICampaign
{
    void ApplyDiscount(ShoppingCart card);
}

The Campaign type which is applied based on a money amount(e.g. 100 USD discount over the price);

public class AmountDiscount : Discount, ICampaign
    {
        public decimal DiscountAmount { get; set; }
        public AmountDiscountGenerator(Category category, int minItems, decimal discountAmount) : base(category, minItems)
        {
            DiscountAmount = discountAmount;
        }

        public void ApplyDiscount(ShoppingCart card)
        {
            card.TotalPrice() -= DiscountAmount;
        }

The Campaign type which is applied based on the rate (e.g. %20 discount over the price);

public class RateDiscountGenerator : Discount, ICampaignGenerator
    {
        public double DiscountRate { get; set; }
        public RateDiscountGenerator(Category category, int minItems, double discountRate) : base(category, minItems)
        {
            DiscountRate = discountRate;
        }

        public void ApplyDiscount(ShoppingCart card)
        {
             card.TotalPrice() -= card.TotalPrice() * DiscountRate / 100;
        }

As you can see, the different campaign classes differs on the ApplyDiscount() method's algorithm. But also, it differs about one of them has the data member named DiscountAmount and the other has DiscountRate.

Here is the factory class which I implemented;

 public static class CampaignFactory
    {
        public static ICampaign GenerateCampaign(Category category, int minItems, int amountOrRate, DiscountType discountType)
        {
            if(discountType == DiscountType.Amount)
            {
                return new AmountDiscountGenerator(category, minItems, amountOrRate);
            }
            else if(discountType == DiscountType.Rate)
            {
                return new RateDiscountGenerator(category, minItems, amountOrRate);
            }
        }
    }

The problem with my factory class is the parameter named amountOrRate. To initialize the properties DiscountAmount or DiscountRate, I need to have a common parameter in my factory class, but since this properties are semantically different, it looks wrong to me to accept a common parameter in my factory method and both campaign class constructors is going to share it(you can understand my confusion from the naming of the parameter amountOrRate).

Can you help me to implement the pattern on this particular example? You can also advice me if I need to implement different design patterns with factory pattern(e.g. strategy pattern). Any help is appreciated, thanks.

Aucun commentaire:

Enregistrer un commentaire