I am trying to implement a system that can handle multiple discounts applied to my cart/completed orders. I have applied a strategy type pattern to encapsulate the processin
As I mentioned in the comments to your question I don't think strategy is apt in this case.
To me all these discounts BuyXGetYFree, SpendMoreThanXGetYDiscount etc are all rules (and may not all neccesarily be about getting discount) that can be applied in calculating product/cart cost. I would build a RulesEngine utilising the rules you outlined and when you ask the cart to calculate its cost process it against the RulesEngine. The RulesEngine would process the product lines making up the cart and the overall order and apply the relevant adjustments to costs etc.
The RulesEngine could even control the order in which the rules are applied.
Rules could be product based (e.g. Buy one get one free) or order based (eg. Buy X items get free shipping) and you could even have expiry dates built in. These rules would be persisted to a data store.
To me the Decorator pattern seems more applicable here. It starts with the a similar Discount class hierarchy you have, but the discounts would also implement OrderBase
. Then they decorate the order instead of just being attached to it. When queried, the decorator gets the order data from the order instance it decorates (which may be a plain vanilla order, or another decorator), and applies to it the appropriate discount. IMO this is fairly easy to implement but also flexible enough; in short, to me this is the simplest solution that may work.
The order of discounts in the decorator chain is probably not arbitrary though; at first guess you should apply price altering discounts first, then quantity altering ones. But I guess this is not a very strong constraint.