A purchase order has an order ID, a customer ID, total price and line items. Line items can be a product or membership type.
Business rules:
- If the purchase order contains a membership, it has to be activated in the customer account immediately.
- If the purchase order contains "Comprehensive First Aid training video," then "Basic First Aid training video" is added to the purchase order
public abstract class Product
{
}
public class BookClubMembership : Product
{
public bool IsActivated { get; set; }
}
Using the strategy design pattern, I define the first rule as follows:
public class BookClubMembershipRule : IPurchaseOrderRule
{
readonly ICustomerActivationService _customerActivationService;
public BookClubMembershipRule(ICustomerActivationService customerActivationService)
{
_customerActivationService = customerActivationService;
}
public void Execute(PurchaseOrder order)
{
foreach(var product in order.Items) {
if (product is BookClubMembership)
{
_customerActivationService.ActivateBookMembership(order.CustomerId, product as BookClubMembership);
break;
}
}
}
}
public class PurchaseOrderProcessor
{
public IList<IPurchaseOrderRule> Rules { get; }
public PurchaseOrderProcessor(List<IPurchaseOrderRule> rules)
{
Rules = rules;
}
public void ProcessOrder(PurchaseOrder order)
{
foreach (var rule in Rules)
rule.Execute(order);
}
I don't feel comfortable using C# is
and as
above. Is there a better way for me to program these rules. I was thinking of Visitor pattern but given the 2nd rule. I will need to operate on the order and the item as well.
A line item is what I call an item in an order. For example, an order can look like this:
Order No: 3344656
Total: 48.50
Customer Id: 4567890
Line items:
• Video "Comprehensive First Aid Training"
• Book "The Girl on the train"
• Book Club Membership
Added code for the second rule:
public class ComprehensiveVideoRule : IPurchaseOrderRule
{
public void Execute(PurchaseOrder order)
{
bool addNewVideo = false;
foreach(var item in order.Items)
{
if(item is Video)
{
var checkItem = item as Video;
if(checkItem.Title.Contains("Comprehensive"))
addNewVideo = true;
}
}
if(addNewVideo) order.Items.Add(new Video("Basic First Aid"));
}
}