APPLYING GOF DESIGN PATTERNS PART 2: STRATEGY & COMPOSITE
Anything you can do, I can do meta. Lecturer: Philip Dart Larman Chapter 26 —Daniel Dennett
SWEN30006
Software Modelling and Design
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Objectives
On completion of this topic you should be able to:
Apply some GoF design patterns o Adapter
o Factory (not GoF) o Singleton
o Strategy
o Composite
o Façade
o Observer (Brief) o Decorator
Recognise GRASP principles as a generalization of other design
5
patterns.
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Problem 2.1: Complex Pricing Logic
POS provides more complex pricing logic, e.g., o store-wide discount for the day
o senior citizen discounts
The pricing strategy for a sale can vary, e.g.,
o one period it may be 10% off all sales
o later it may be $10 off if the sale total is greater than $200
6
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Strategy (GoF)
Problem:
How to design for varying, but related, algorithms or policies?
How to design for the ability to change these algorithms or policies?
Solution (advice):
Define each algorithm/policy/strategy in a separate class, with a common interface.
7
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Pricing Strategy Classes
«interface» ISalePricingStrategy
getTotal( Sale ) : Money
PercentDiscount ???
PricingStrategy
getTotal( s:Sale ) : Money
PricingStrategy
…
…
percentage : float
AbsoluteDiscount OverThreshold PricingStrategy
discount : Money threshold : Money
getTotal( s:Sale ) : Money
{pdt := s.getPreDiscountTotal() if ( pdt < threshold )
return pdt else
} return pdt - discount
{ return s.getPreDiscountTotal() * percentage }
8
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Context Object Visibility to Strategy
Sale needs attribute visibility to its Strategy
Context Object
Sale
1 pricingStrategy
«interface» ISalePricingStrategy
date ...
getTotal( Sale ) : Money
getTotal() ...
getTotal()
{...
return pricingStrategy.getTotal( this )
}
PercentDiscount PricingStrategy
percentage : float
getTotal( Sale ) : Money
AbsoluteDiscount OverThreshold PricingStrategy
discount : Money threshold : Money
9
getTotal( Sale ) : Money
SWEN30006 Software Modelling and Design Applying GoF Design Patterns Strategy in Collaboration
s : Sale t = getTotal
loop
lineItems[ i ] : SalesLineItem
:PercentDiscount PricingStrategy
st = getSubtotal
{ t = pdt * percentage }
note that the Sale s is passed to the Strategy so that it has parameter visibility to it for further collaboration
t = getTotal( s ) pdt = getPreDiscountTotal
10
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example
public interface ISalePricingStrategy {
} public double getTotal(Sale s); ISalePricingStrategy.java
public class PercentDiscountPricingStrategy implements ISalePricingStrategy{ private double percentage = 0.05;
public double getTotal(Sale s) {
return s.getPreDiscountTotal() -
(s.getPreDiscountTotal() * percentage); }}
PercentDiscountPricingStrategy.java
11
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example (cont)
public class AbsoluteDiscountOverThresholdPricingStrategy implements ISalePricingStrategy { private double threshold = 50;
private double discount = 5; public double getTotal(Sale s) {
} }}
double pdt = s.getPreDiscountTotal(); if(pdt >= threshold) {
return pdt – discount;
}else {
return pdt;
AbsoluteDiscountOverThethresholdPricingStrategy.java
12
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Creation: Factory for Strategies
Strategy not stored.
New strategy created for every request.
1 PricingStra tegyFactory
instance : PricingStrategyFactory
getInstance() : PricingStrategyFactory
getSalePricingStrategy() : ISalePricingStrategy getSeniorPricingStrategy() : ISalePricingStrategy …
{ String className = System.getProperty( “salepricingstrategy.class.name” ); strategy = (ISalePricingStrategy) Class.forName( className ).newInstance();
} return strategy;
13
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Creating a Strategy
:Register
1 :PricingStrategyFactory
makeNewSale
create
:Sale
ps = getSalePricingStrategy
create(percent)
ps : PercentDiscount PricingStrategy
14
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Problem 2.2: Multiple Conflicting Policies
E.g. suppose the stores pricing today (Monday) is:
20% senior discount policy
preferred customer discount: 15% off sales over $400
on Monday, there is $50 off purchases over $500
buy 1 case Darjeeling tea, get 15% discount off everything
Factors:
1. customer type (senior, preferred)
2. time period (Monday)
3. line item product (Darjeeling tea)
17
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Combining Policies
conflict resolution strategy:
when multiple policies are applicable, how are these policies resolved?
o Some discounts cannot be combined with others
o Possiblepolicies:BestforcustomerorBestforstore
Composite pricing strategy:
Determine which pricing strategies are applicable Apply the relevant conflict resolution strategy
18
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Composite (GoF)
Problem:
How to treat a group or composition structure of objects the same way (polymorphically) as a non- composite (atomic) object?
Solution (advice):
Define classes for composite and atomic objects so that they implement the same interface.
19
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Composite: Generalised Structure
20
SWEN30006 Software Modelling and Design Applying GoF Design Patterns Example 1: Composite shape
Circle.draw(g) Line.draw(g)
Rectangle.draw(g) Picture.draw(g) 21
Rectangle
+ addShape(s: Shape)
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example: Main
public class CompositeDrawing {
public static void main(String[] args) {
Circle circle1 = new Circle(5,new Point(0,0));
Rectangle rectangle1 = new Rectangle(new Point(0,10),new Point(10,20)); Line line1 = new Line(new Point(5,10),new Point(0,10));
Picture myPicture = new Picture();
myPicture.addShape(circle1); myPicture.addShape(rectangle1); myPicture.addShape(line1); myPicture.draw();
}}
22
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example: Picture (Composite Shapes)
public class Picture extends Shape{ ArrayList
public Picture() {
} shapes = new ArrayList
public void addShape(Shape shape) { } shapes.add(shape);
public void draw() { for(Shape s: shapes) {
}}} s.draw();
23
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example2: Composite characters
Create a group of characters for DisneyMadness
o Update the current diagram to use composite Disney Army
24
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
(Problem 2.2) Combining Policies
conflict resolution strategy:
when multiple policies are applicable, how are these policies resolved?
o Some discounts cannot be combined with others
o Possiblepolicies:BestforcustomerorBestforstore
Composite pricing strategy:
Determine which pricing strategies are applicable Apply the relevant conflict resolution strategy
28
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Composite Strategies
{
…
return pricingStrategy.getTotal( this ) }
All composites maintain a list of contained strategies. Therefore, define a common superclass CompositePricingStrategy that defines this list (named strategies).
Sale
date …
getTotal() …
Strategy Pattern
1 pricingStrategy
PercentageDiscount PricingStrategy
«interface» ISalePricingStrategy
1..* strategies
Composite PricingStrategy
getTotal( Sale ) : Money
AbsoluteDiscount OverThreshold PricingStrategy
discount : Money threshold : Money
getTotal( Sale ) : Money
add( ISalePricingStrategy )
getTotal( Sale ) : Money
percentage : float
getTotal( Sale ) : Money
CompositeBestForStore PricingStrategy
getTotal( Sale ) : Money
CompositeBestForCustomer PricingStrategy
getTotal( Sale ) : Money
{
return sale.getPreDiscountTotal() *
percentage }
29
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Composite Strategies
Composite Pattern
30
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Composite Strategies
Abstract class
31
SWEN30006 Software Modelling and Design Applying GoF Design Patterns Collaboration with a Composite
s : Sale
t = getTotal
loop
lineItems[ i ] : SalesLineItem
:CompositeBestForCustomer PricingStrategy
t = getTotal( s )
strategies[ j ] :
: ISalePricingStrategy
st = getSubtotal
{ t = min(set of all x) }
loop
x = getTotal( s )
the Sale object treats a Composite Strategy that contains other strategies just like any other ISalePricingStrategy
UML: ISalePricingStrategy is an interface, not a class; this is the way in UML 2 to indicate an object of an unknown class, but that implements this interface
33
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Creating a Composite Strategy
make NewSale
:Register
1 :PricingStrategyFactory
create
:Sale
ps = getSale PricingStrategy
create
create( percent ) add( s )
ps :CompositeBestForCustomer PricingStrategy
s : PercentageDiscount PricingStrategy
34
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example
public interface ISalePricingStrategy { public double getTotal(Sale s);
}
public String getStrategyName();
ISalePricingStrategy.java
abstract class CompositePricingStrategy implements ISalePricingStrategy { protected ArrayList
ArrayList
public void add(ISalePricingStrategy strategy) { pricingStrategies.add(strategy);
}
public abstract double getTotal(Sale s); }
CompositePricingStrategy.java
35
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example: Composite Strategy
public class CompositeBestForCustomerPricingStrategy extends CompositePricingStrategy { private String selectedStrategy = null;
//Get minimum total
public double getTotal(Sale s) {
double lowestTotal = s.getPreDiscountTotal();
for(ISalePricingStrategy strat: this.pricingStrategies){ double total = strat.getTotal(s);
if(lowestTotal > total) {
} } lowestTotal = total;
return lowestTotal; }}
36
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Example: Composite Strategy Factory
public class PricingStrategyFactory {
public ISalePricingStrategy getCompositeSalePricingStrategy() {
ISalePricingStrategy applicableStrategies = null; LocalDateTime today = LocalDateTime.now(); switch(today.getDayOfWeek()) {
case MONDAY:
CompositePricingStrategy composStrat = new
CompositeBestForCustomerPricingStrategy(); composStrat.add(new PercentDiscountPricingStrategy()); composStrat.add(new TeaDiscountPricingStrategy()); applicableStrategies = composStrat;
break;
case FRIDAY: applicableStrategies = new
AbsoluteDiscountOverThresholdPricingStrategy(); break;
}
return applicableStrategies;
}}
37
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Extension (or Alternative Flows)
Customer says they are eligible for a discount (e.g., employee, preferred customer)
o Cashier signals discount request.
o Cashier enters Customer identification.
o System presents discount total, based on discount rules.
39
SWEN30006 Software Modelling and Design Applying GoF Design Patterns Creating Discount Pricing Strategy (1)
enterCustomerForDiscount( custID )
by Controller
by Expert and IDs to Objects
:Register
by Expert
:Store
c = getCustomer( custID ) enterCustomerForDiscount( c : Customer )
ref
Enter Customer For Discount
s :Sale
40
SWEN30006 Software Modelling and Design Applying GoF Design Patterns Creating Discount Pricing Strategy (2)
sd Enter Customer For Discount
by Expert
enterCustomer ForDiscount( c : Customer )
by Expert
by Factory and High Cohesion
s :Sale
:PricingStrategy Factory
ps :CompositeBestForCustomer PricingStrategy
addCustomer PricingStrategy( s )
c = getCustomer
ps = getPricing Strategy
by High Cohesion
1
Pass Aggregate Object as Parameter
pct = getCustomer Percentage( c )
create( pct ) add(cs )
by Factory and Composite
cs : PercentageDiscount PricingStrategy
41
SWEN30006 Software Modelling and Design Applying GoF Design Patterns
Summary: Complex Pricing Logic
POS has various pricing strategies/discounts and some of them cannot be combined
Solution:
“To handle this problem, let’s use Composite Strategy” Design reasoning based on:
o ProtectedVariation o Polymorphism
o HighCohesion
o Low Coupling
o Strategy
o Composite o Factory
o Singleton
42
Next Lecture: 1. Façade
2. Observer 3. Decorator
Lecture Identification
Coordinator/Lecturer: Philip Dart
Semester: S1 2021
© University of Melbourne 2021 These slides include materials from:
Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, Third Edition, by Craig Larman, Pearson Education Inc., 2005.
45