Skip to content

Commit 11222e0

Browse files
committed
Added Rules Pattern
1 parent fa3886b commit 11222e0

11 files changed

Lines changed: 182 additions & 1 deletion
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Rules
4+
{
5+
public class BirthdayDiscountRule : IDiscountRule
6+
{
7+
public decimal CalculateCustomerDiscount(DiscountCustomer customer)
8+
{
9+
if (customer.DateOfBirth.Month == DateTime.Today.Month &&
10+
customer.DateOfBirth.Day == DateTime.Today.Day)
11+
{
12+
return 0.10m;
13+
}
14+
return 0;
15+
}
16+
}
17+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace SoftwarePatterns.Core.Rules
5+
{
6+
public class DiscountCalculator
7+
{
8+
private readonly List<IDiscountRule> _discountRules;
9+
10+
public DiscountCalculator()
11+
{
12+
_discountRules = new List<IDiscountRule>
13+
{
14+
new BirthdayDiscountRule(),
15+
new SeniorDiscountRule(),
16+
new VeteransDiscountRule(),
17+
new FirstPurchaseRule(),
18+
new LoyalCustomerDiscount(1,0.05m),
19+
new LoyalCustomerDiscount(5,0.15m),
20+
new LoyalCustomerDiscount(5,0.20m)
21+
};
22+
}
23+
24+
public decimal CalculateDiscountPercentage(DiscountCustomer customer)
25+
{
26+
decimal discount = 0;
27+
28+
_discountRules.ForEach(rule =>
29+
{
30+
discount = Math.Max(rule.CalculateCustomerDiscount(customer), discount);
31+
});
32+
33+
return discount;
34+
}
35+
}
36+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Rules
4+
{
5+
public class DiscountCustomer
6+
{
7+
public DateTime DateOfBirth { get; set; }
8+
public bool IsVeteran { get; set; }
9+
public DateTime? DateOfFirstPurchase { get; set; }
10+
}
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Rules
4+
{
5+
public class FirstPurchaseRule : IDiscountRule
6+
{
7+
public decimal CalculateCustomerDiscount(DiscountCustomer customer)
8+
{
9+
if (customer.DateOfFirstPurchase.HasValue && customer.DateOfFirstPurchase.Value == DateTime.Today)
10+
return 0.05m;
11+
return 0;
12+
}
13+
}
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace SoftwarePatterns.Core.Rules
2+
{
3+
public interface IDiscountRule
4+
{
5+
decimal CalculateCustomerDiscount(DiscountCustomer customer);
6+
}
7+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Rules
4+
{
5+
public class LoyalCustomerDiscount : IDiscountRule
6+
{
7+
private readonly int _yearsCustomer;
8+
private readonly decimal _discount;
9+
10+
public LoyalCustomerDiscount(int yearsCustomer, decimal discount)
11+
{
12+
_yearsCustomer = yearsCustomer;
13+
_discount = discount;
14+
}
15+
16+
public decimal CalculateCustomerDiscount(DiscountCustomer customer)
17+
{
18+
var discount = 0m;
19+
if (customer.DateOfFirstPurchase != null &&
20+
customer.DateOfFirstPurchase.Value.AddYears(_yearsCustomer) >= DateTime.Today)
21+
{
22+
var rule = new BirthdayDiscountRule();
23+
discount = _discount + rule.CalculateCustomerDiscount(customer);
24+
}
25+
26+
return discount;
27+
}
28+
}
29+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Define:
2+
To divide a complex set of business logic into a set of separate business rules. This separates the rules logic from the process by which rules are applied.
3+
4+
Intent:
5+
Separate individual rules from processing logic
6+
Allow rules to be added without the need for changes in the rest of the system
7+
8+
Considerations:
9+
Good idea to keep rules read only so they have little effect on other parts of the system
10+
Try and reduce rule dependencies where possible
11+
Do rules need to be run in explicit order
12+
Rules could have a priority order which they can then be ordered by
13+
Some rules may trump others so you may want to include halt mechanism
14+
You may need to be able to persist rules and let end user edit them
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Rules
4+
{
5+
public class SeniorDiscountRule : IDiscountRule
6+
{
7+
public decimal CalculateCustomerDiscount(DiscountCustomer customer)
8+
{
9+
return customer.DateOfBirth < DateTime.Now.AddYears(-65) ? 0.05m : 0;
10+
}
11+
}
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace SoftwarePatterns.Core.Rules
2+
{
3+
public class VeteransDiscountRule : IDiscountRule
4+
{
5+
public decimal CalculateCustomerDiscount(DiscountCustomer customer)
6+
{
7+
return (customer.IsVeteran) ? 0.05m : 0;
8+
}
9+
}
10+
}

src/SoftwarePatterns.Core/SoftwarePatterns.Core.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@
174174
<Compile Include="Repository\IProjectRepository.cs" />
175175
<Compile Include="Repository\IRepository.cs" />
176176
<Compile Include="Repository\Project.cs" />
177+
<Compile Include="Rules\BirthdayDiscountRule.cs" />
178+
<Compile Include="Rules\DiscountCalculator.cs" />
179+
<Compile Include="Rules\DiscountCustomer.cs" />
180+
<Compile Include="Rules\FirstPurchaseRule.cs" />
181+
<Compile Include="Rules\IDiscountRule.cs" />
182+
<Compile Include="Rules\LoyalCustomerDiscount.cs" />
183+
<Compile Include="Rules\SeniorDiscountRule.cs" />
184+
<Compile Include="Rules\VeteransDiscountRule.cs" />
177185
<Compile Include="ServiceLocator\IPackageProccessor.cs" />
178186
<Compile Include="ServiceLocator\IPackageProcessor.cs" />
179187
<Compile Include="ServiceLocator\IPackageShipper.cs" />
@@ -234,6 +242,7 @@
234242
<Content Include="PatternList.txt" />
235243
<Content Include="Proxy\ReadMe.txt" />
236244
<Content Include="Repository\ReadMe.txt" />
245+
<Content Include="Rules\ReadMe.txt" />
237246
<Content Include="ServiceLocator\ReadMe.txt" />
238247
<Content Include="Singleton\ReadMe.txt" />
239248
<Content Include="State\ReadMe.txt" />
@@ -246,6 +255,7 @@
246255
<None Include="App.config" />
247256
<None Include="packages.config" />
248257
</ItemGroup>
258+
<ItemGroup />
249259
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
250260
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
251261
Other similar extension points exist, see Microsoft.Common.targets.

0 commit comments

Comments
 (0)