Design Patterns
Yonglei Tao
Design Patterns A design pattern describes a recurring
design problem, a solution, and the context in which that solution works A common way of doing things Specialization of a design principle Tested knowledge A named description of a technique with its
benefits and costs
The Strategy Pattern Problem
how to design for varying, but related, algorithms or policies
how to design for the ability to change them Solution
define a family of algorithms, encapsulate each one in a separate class, and make them interchangeable
A Sorting Example Shellsort
No extra space needed, fast but not optimal Very fast on nearly sorted data Does comparatively well on small lists
Quicksort Average case is O (n log n) Relatively poor performance on short lists Require a stack of log(n) in depth
Mergesort Worst case is O (n log n) Requires O (n) extra space Stable
Sorting (cont.) Have a sorted list container, which one gives a
sort algorithm
SortedList studentRecords = new SortedList( new ShellSort() );
studentRecords.add( “Sam” ); …
pubic class SortedList { Object[ ] elements;
SortStrategy sorter;
void sort( ) { sorter.sort( elements); } }
Sale
+Total() : Money-policy : IDiscountPolicy
«Interface»IDiscountPolity
+getDiscount(sale : Sale) : M oney
DiscountPolicyA
+getDiscount()
DiscountPolicyB
+getDiscount()
DiscountPolicyC
+getDiscount()
Money Total () { get subtotals and calculate sum ; d iscount = policy.getD iscount(this); return sum - discount;}
More on Strategy
:PercentDiscountPricingStrategy
s : Sale
st = getSubtotal
t = getTotal
lineItems[ i ] :SalesLineItem
t = getTotal( s )
pdt = getPreDiscountTotal
{ t = pdt * percentage }
note that the Sale s is passed to the Strategy so that it has parameter visibility to it for further collaboration
loop
t = getDiscount(s)
The Factory Pattern Problem
a class cannot anticipate the class of objects it must create
how to handle object creation with complex creation logic or other special considerations
Solution encapsulate the knowledge of object creation
and move it out of the class that uses the object
define an interface for creating an object, but let subclasses decide which class to instantiate
Factory Method
Document
+open()+close()+save()
Application
+createDocum ent()+newDocum ent()+openDocum ent()
MyDoc
MyApp
+createDocum ent()
// new Document ()Docum ent doc = createDocument();docList.Add(doc);doc.open();
// createDocument() - Template M ethodreturn new M yDoc();
// the m ain methodM yApp app;app.New Document ();Application-Sepcific
Fram ework
The Singleton Pattern Problem
objects need a global and single point of access Solution
ensure a class has exactly one instance define a static method that returns the singleton
Consequences facilitates communication between objects not
directly coupled reduce coupling between objects in a system
Singleton
instance: S ingleton
Singleton();getInstance():S ingleton
{ // static m ethod if (instance == null) instance = new Singleton(); return instance;}
// get a reference to the singleton object
theSingleton = Singleton.getInstance();
The Singleton Pattern
Implementationclass Singleton {
private static Singleton _instance = null; private Singleton() { … } public static Singleton getInstance() {
if ( _instance == null ) _instance = new Singleton();
return _instance; } public void otherOperations() { … }
} class Program {
public void aMethod() { X = Singleton.getInstance();
} }
Factory
1PricingStrategyFactory
instance : PricingStrategyFactory
getInstance() : PricingStrategyFactory
getSalePricingStrategy() : ISalePricingStrategygetSeniorPricingStrategy() : ISalePricingStrategy...
{ String className = System.getProperty( "salepricingstrategy.class.name" ); strategy = (ISalePricingStrategy) Class.forName( className ).newInstance(); return strategy; }
Factory
:Sale
1:PricingStrategyFactory
ps =getSale
PricingStrategy
:Register
makeNewSale create
create ps :CompositeBestForCustomerPricingStrategy
create( percent ) s : PercentageDiscountPricingStrategy
add( s )
Navigational Model for Visual C++
:M yApp
:M yView
:CM ainFram e
:M yDoc
m_pM ainW nd
G etDocument()
G etActiveDoc()
G etActiveView ()
A S ingleton objectaccessible throughthe global functionAfxG etApp()
Example: the Null Node in Binary Trees
public class BinaryNode extends Node { Node left , right; int key;
public boolean includes( int value ) { if (key == value)
return true; else if (value < key )
return left.includes( value ); else
return right.includes(value); }
… }
public class NullNode extends Node { public boolean includes( int value ) {
return false; }
… }
The Composite Pattern Problem
How to allow clients to treat individual objects and compositions of objects uniformly
Solution Organize objects into a tree structure that
represents an aggregation hierarchy
Client
«Interface»Component
+operation() : void+addCom ponent() : void+rem oveCom ponent() : void+getChild(n : int) : Com ponent
Composite
+operation() : void+addCom ponent() : void+rem oveCom ponent() : void+getChild(n : int) : Com ponent
Leaf
+operation() : void
Structure
Use of Composite
PercentageDiscountPricingStrategy
percentage : float
getTotal( Sale ) : Money
AbsoluteDiscountOverThresholdPricingStrategy
discount : Moneythreshold : Money
getTotal( Sale ) : Money
«interface»ISalePricingStrategy
getTotal( Sale ) : Money
{ return sale.getPreDiscountTotal() * percentage }
CompositePricingStrategy
add( ISalePricingStrategy )getTotal( Sale ) : Money
{lowestTotal = INTEGER.MAXfor each ISalePricingStrategy strat in pricingStrategies { total := strat.getTotal( sale ) lowestTotal = min( total, lowestTotal ) }return lowestTotal }
1..*
CompositeBestForCustomerPricingStrategy
getTotal( Sale ) : Money
CompositeBestForStorePricingStrategy
getTotal( Sale ) : Money
strategies
All composites maintain a list of contained strategies. Therefore, define a common superclass CompositePricingStrategy that defines this list (named strategies).
Sale
date...
getTotal()...
1
pricingStrategy
{...return pricingStrategy.getTotal( this )}
More on Composite
:CompositeBestForCustomerPricingStrategy
s : Sale
st = getSubtotal
t = getTotal
lineItems[ i ] :SalesLineItem
t = getTotal( s )
the Sale object treats a Composite Strategy that contains other strategies just like any other ISalePricingStrategy
x = getTotal( s )
strategies[ j ] :: 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
{ t = min(set of all x) }
loop
loop