GoF

CSC 440: Software Engineering Slide #1 Topics

1. GoF Design Patterns 2. Template Method 3. Strategy 4. Composite 5. Adapter

CSC 440: Software Engineering Slide #2 Design Patterns Book

 Classic text that started Design Patterns movement written by the Gang of Four (GoF).  We’ll introduce several widely used patterns from the book.  Useful solutions for certain problems, but if you don’t have the problem, don’t use the pattern.

CSC 440: Software Engineering Slide #3 GoF Design Patterns Catalog

Behavioral Creational Structural

 Interpreter  Factory  Adapter  Template  Abstract Factory  Bridge method  Builder  Chain of  Composite Responsibility  Prototype  Decorator  Command  Singleton  Façade  Iterator  Flyweight  Mediator  Memento  Proxy  Observer  State  Strategy  Visitor

CSC 440: Software Engineering Slide #4 GoF and GRASP Patterns

GoF patterns are specializations and/or combinations of the more fundamental GRASP design patterns.  Example: Adapter Pattern provides Protected Variations through use of Indirection and Polymorphism

CSC 440: Software Engineering Slide #5 Template Method

 Pattern Name: Template Method  Problem: How to implement an algorithm that varies in certain circumstances?  Solution: Define the skeleton of the algorithm in the superclass, deferring implementation of the individual steps to the subclasses.

CSC 440: Software Engineering Slide #6 Example: The Report Class class Report def output_report(format) if format == :plain puts(“*** #{@title} ***”) elsif format == :html puts(“”) puts(“#{@title}”) puts(“”) else raise “Unknown format” end # similar code for body, ending, etc. end end

CSC 440: Software Engineering Slide #7 Report with Template Method class Report def output_report(format) output_start() output_head() output_body() output_end() end end

CSC 440: Software Engineering Slide #8 HTMLReport class HTMLReport < Report def output_start puts(“html”) end def output_head() puts(“#{@title}”) end def output_body() puts(“…”) end def output_end() puts(“”) end end

CSC 440: Software Engineering Slide #9 PlainTextReport

class PlainTextReport < Report def output_start end def output_head() puts(“*** #{@title} ***”) end def output_body() puts(“…”) end def output_end() end end

CSC 440: Software Engineering Slide #10 Strategy

 Pattern Name: Strategy  Problem: How to design for varying, but related, algorithms or policies without using inheritance? Solution: Write each algorithm in its own class, with a common and use algorithm classes via object composition.

CSC 440: Software Engineering Slide #11 Abstract Formatter Class class Formatter def output_report(title, text) raise “Abstract method called.” end end

CSC 440: Software Engineering Slide #12 HTML Formatter Class

class HTMLFormatter < Formatter def output_report(title, text) puts(“) puts(“#{title}”) puts(“#{text}”) puts(“”) end end

CSC 440: Software Engineering Slide #13 PlainText Formatter Class

class PlainTextFormatter < Formatter def output_report(title, text) puts(“*** #{title} ***”) puts(text) end end

CSC 440: Software Engineering Slide #14 POS Strategy Example

 How do we handle different sale pricing policies in the POS system?  10% off  $10 off if over $200  Solution: Create multiple SalePricingStrategy classes, each with a polymorphic getTotal() method that implements the particular policy described by that class.

CSC 440: Software Engineering Slide #15 Strategy Example

«interface» ISalePricingStrategy

g e tT o ta l( S a le ) : M o n e y

PercentDiscount AbsoluteDiscount ??? PricingStrategy OverThreshold PricingStrategy PricingStrategy percentage : flo a t ... d is c o u n t : M o n e y g e tT o ta l( s :S a le ) : th re s h o ld : M o n e y ... M o n e y g e tT o ta l( s :S a le ) : M o n e y

{ { re tu rn s .getPreDiscountTotal() * percentage p d t := s .getPreDiscountTotal() } if ( p d t < th re s h o ld ) return pdt e ls e return pdt - d is c o u n t } CSC 440: Software Engineering Slide #16 Context Objects

 A strategy object is attached to a context object—the object to which it applies its algorithm.  In this example, the context object is a Sale.  The context object is often passed as an argument to the strategy object as an argument, e.g. self or this.  When a getTotal() method is sent to a Sale, it delegates some of the work to its strategy object.

CSC 440: Software Engineering Slide #17 Collaboration of Sale and Strategy Objects

lin e Ite m s [ i ] : :PercentDiscount s : S a le SalesLineItem PricingStrategy

t = g e tT o ta l

{ t = p d t * percentage } s t = getSubtotal lo o p

t = g e tT o ta l( s )

p d t = getPreDiscountTotal note that the Sale s is passed to the Strategy so that it has parameter visibility to it for further collaboration

CSC 440: Software Engineering Slide #18 Collaboration of Sale and Strategy Objects

Sale needs attribute visibility to its Strategy

S a le

«interface» d a te 1 ISalePricingStrategy ...

pricingStrategy g e tT o ta l( S a le ) : M o n e y g e tT o ta l() ...

g e tT o ta l() PercentDiscount AbsoluteDiscount { PricingStrategy OverThreshold ... PricingStrategy return pricingStrategy .g e tT o ta l( th is ) percentage : flo a t d is c o u n t : M o n e y } g e tT o ta l( S a le ) : M o n e y th re s h o ld : M o n e y

g e tT o ta l( S a le ) : M o n e y

CSC 440: Software Engineering Slide #19 Discussion

 Strategy provides Protected Variations with respect to changing algorithms.  Strategy is a specialization of Polymorphism.  Passing the context object as an argument enables easy collaboration and visibility, but it also increases coupling.

CSC 440: Software Engineering Slide #20 Composite  Pattern Name: Composite  Problem: How to treat a group of objects the same way (polymorphically) as a non-composite (leaf or atomic) object? How to create a tree of objects?  Solution: Define classes for composite and leaf objects that implement identical interfaces.

CSC 440: Software Engineering Slide #21 Composite Example

CSC 440: Software Engineering Slide #22 Abstract Component Class class Task def initialize(name) @name = name end def name return @name end def get_time_required return 0.0 end end

CSC 440: Software Engineering Slide #23 Example Leaf Class class MixTask < Task def initialize(name) super(“Mix the batter”) end def get_time_required return 3.0 end end

CSC 440: Software Engineering Slide #24 Example Composite Class class MakeBatterTask < Task def initialize(name) super(“Make batter”) @sub_tasks = Array.new add_sub_task(AddLiquidsTask.new) add_sub_task(MixTask.new) end

def get_time_required time = 0.0 @sub_tasks.each { |t| time += t.get_time_required } return time end end CSC 440: Software Engineering Slide #25 Example Composite Class class MakeBatterTask < Task def add_sub_task(task) @sub_tasks.push(task) end

def remove_sub_task(task) @sub_tasks.delete(task) end end

CSC 440: Software Engineering Slide #26 POS Composite Example

Problem: How do we handle the case of multiple, conflicting pricing policies?  20% senior discount  preferred customer discount of 15% of sales over $400  today there is a $50 off purchases over $500  buy 1 case of Darjeeling, get 15% discount off everything

CSC 440: Software Engineering Slide #27 Composite Example

 Pricing strategies attach to sale by virtue of:  Time period.  Customer type.  A particular line item.  Need to define a conflict resolution strategy.  How can we modify design to Sale object doesn’t know if there are one or many pricing strategies and also provide for conflict resolution?

CSC 440: Software Engineering Slide #28 POS Composite Example Add new CompositePricingStrategy class  Abstract class.  Has two concrete subclasses that provide for different conflict resolution strategies:  CompositeBestForCustomerPricingStrategy  CompositeBestForStorePricingStrategy  Polymorphically provides getTotal() method, so it can be called like any other PricingStrategy.  add( PricingStrategy ) method allows set of PricingStrategy objects to be composed together.

CSC 440: Software Engineering Slide #29 { All composites maintain a list of ... contained strategies . T h e re fo re , return pricingStrategy .g e tT o ta l( th is ) define a common superclass Example } CompositePricingStrategy th a t defines this list (n a m e d s tra te g ie s ).

S a le

«interface» d a te 1 ..* 1 ISalePricingStrategy ... pricingStrategy g e tT o ta l( S a le ) : M o n e y s tra te g ie s g e tT o ta l() ...

PercentageDiscount AbsoluteDiscount C o m p o s ite PricingStrategy OverThreshold PricingStrategy PricingStrategy percentage : flo a t d is c o u n t : M o n e y g e tT o ta l( S a le ) : M o n e y th re s h o ld : M o n e y add( ISalePricingStrategy ) g e tT o ta l( S a le ) : M o n e y g e tT o ta l( S a le ) : M o n e y

{ CompositeBestForCustomer CompositeBestForStore return sale .getPreDiscountTotal() * PricingStrategy PricingStrategy percentage }

g e tT o ta l( S a le ) : M o n e y g e tT o ta l( S a le ) : M o n e y

{ lowestTotal = INTEGER .MAX for each ISalePricingStrategy strat in pricingStrategies { to ta l := s tra t.g e tT o ta l( s a le ) lowestTotal = m in ( to ta l, lowestTotal ) } return lowestTotal } CSC 440: Software Engineering Slide #30 POS Composite Sequence

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

lin e Ite m s [ i ] : :CompositeBestForCustomer s tra te g ie s [ j ] : s : S a le SalesLineItem PricingStrategy : ISalePricingStrategy

t = g e tT o ta l

s t = getSubtotal lo o p

t = g e tT o ta l( s )

{ t = m in (set of all x ) } lo o p x = g e tT o ta l( s )

th e S a le object treats a Composite Strategy that contains other strategies just like any other ISalePricingStrategy

CSC 440: Software Engineering Slide #31 Discussion

 Core of is:  Outer composite object contains a list of inner objects.  Both inner and outer objects implement the same interface.  Sale object cannot distinguish whether it’s using an atomic or composite PricingStrategy object.

CSC 440: Software Engineering Slide #32 Adapter  Pattern Name: Adapter  Problem: How to resolve incompatible interfaces, or provide a stable interface to similar components with different interfaces?  Solution: Convert the original interface of a component into another interface, through an intermediate adapter object.

CSC 440: Software Engineering Slide #33 Adapter Example Class Diagrams

«interface» Adapters use interfaces and ITaxCalculatorAdapter polymorphism to add a level of indirection to varying APIs in other g e tT a x e s ( S a le ) : List of TaxLineItems c o m p o n e n ts .

TaxMasterAdapter GoodAsGoldTaxPro A d a p te r

g e tT a x e s ( S a le ) : List of TaxLineItems g e tT a x e s ( S a le ) : List of TaxLineItems

«interface» «interface» IAccountingAdapter ICreditAuthorizationService A d a p te r postReceivable ( CreditPayment ) p o s tS a le ( S a le ) requestApproval(CreditPayment,T e rm in a lID , M e rc h a n tID ) ......

«interface» IInventoryAdapter SAPAccountingAdapter GreatNorthernAccountingAdapter ...

postReceivable ( CreditPayment ) postReceivable ( CreditPayment ) p o s tS a le ( S a le ) p o s tS a le ( S a le ) ...... Adapter Example Sequence Diagram

:R e g is te r : SAPAccountingAdapter

makePayment ... S O A P o v e r HTTP

p o s tS a le ( s a le ) xxx « a c to r» : S A P S y s te m

the Adapter adapts to interfaces in other components

CSC 440: Software Engineering Slide #35 Updating the Domain Model

 Adapter design introduced a new domain ... S a le concept: the TaxLineItem 1 ... d a te

tim e  Discovery of new domain C o n ta in s concepts is natural in an 1 C o n ta in s ... iterative process. 1 ..* 1 ..* ... S a le s T a x  Update Domain Model L in e Ite m L in e Ite m

only if you will be using it q u a n tity description p e rc e n ta g e in future iterations. a m o u n t

CSC 440: Software Engineering Slide #36 References 1. Gamma, Helm, Johnson, Vlissides, Design Patterns, Addison-Wesley, 1994. 2. Craig Larman, Applying UML and Patterns, Third Edition, Prentice Hall, 2005. 3. Russ Olsen, Design Patterns in Ruby, Addison- Wesley, 2008. 4. Shalloway and Trott, Design Patterns Explained, Second Edition, 2005.

CSC 440: Software Engineering Slide #37