4

Trying to solve bogo coupon logic with proper design pattern, but having trouble identifying one.
Use case: "Buy iPad get SmartCase for free"

Suppose we have the following objects:

Product:
 - getPrice

CartItem(Product p, quantity):
 - getPrice

Cart:
 - getItems()
 - addItem(CartItem ci)

Coupon(code):
 - getCode

CouponBuyOneGetOneFree(code) extends Coupon: (not sure about inheritance here)

1) What design pattern fits here?
2) What if i needed to set up the same logic without coupon but in product settings itself?

I have implemented Decorator pattern for CartItem when discount is applied to the same CartItem by this example and it works great, but still can not achieve the result of this use case.

Somehow I need to check that Ipad and SmartCase both are in the cart and apply discount to SmartCase only. Also if I add another iPad i should get another SmartCase for free.

2
  • The price of each item depends on the cart as a whole. I would add a PricingService(Cart cart) which sets the price of each item according to your discount logic
    – Ewan
    Jan 9, 2016 at 12:32
  • that is something i am trying to do. just can not decide should this service return discount price or update the CartItem->discount value. i thought maybe i am missing some kind of pattern here.
    – Putna
    Jan 9, 2016 at 12:40

2 Answers 2

5

No design pattern is required beside basic subclassing. You just need a Coupon interface with a single method: calculateDiscount(cart, customer). Create an implementation of Coupon for each different kind of discount, e.g. a FreeAddonCoupon or a LoyaltyCoupon.

So a Cart has CartItems and Coupons. Add the price of the items, subtract the discount for each coupon.

3
  • so i basicly just add discount=0 property to CartItem and update its value with calculateDiscount method, right?
    – Putna
    Jan 9, 2016 at 10:04
  • @Putna: No. The total price of the cart should be calculated by adding the prices of the items and then subtracting the discounts of the coupons. There is no reason for a CartItem to know about the possibility of a discount. Jan 9, 2016 at 12:05
  • 2
    i want to display the amount of discount for each item in the cart, something like striketrough price.
    – Putna
    Jan 9, 2016 at 12:10
2

Real world process seems suitable here. I would separate collection of Coupons from Cart (CartItems collection) by encapsulating them in Checkout object.

Items in cart have its standard price until coupons changes it. Discounts are given at checkout and so does free items. Checkout process goes like this:

  1. Each CartItem is taken out from cart and becomes CheckoutItem
  2. CheckoutItem has additional property - discount (0 at start)
  3. Each Coupon takes a peak at CheckoutItem collection and based on what's in there:
    • increases discount of single item,
    • adds "free" item
    • adds "meta-item" with negative price (total/subtotal discounts)
  4. Additional items are ignored by subsequent coupons (price > 0 should suffice) to avoid cascade effect
  5. Coupons that changed something at checkout are taken away from user
  6. After iterating all coupons CheckoutItems properties may be presented back to user and create order eventually.

Ps. Checkout might not be right name when coupons show its value up front (before adding item to cart), but process shouldn't change imo.

1
  • introducing 'Checkout' object is worth trying. It is a good name, because coupons are applied to cart only. my current implementation is similar, but CartItem has discount property.
    – Putna
    Jan 10, 2016 at 8:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.