Slide 1What will we learn?Slide 3Slide 4CompositeCompositeCompositeSlide 8Slide 9CompositeCompositeSlide 12CompositeSlide 14CompositeCompositeSlide 17Slide 18CompositeFacadeFacadeFacadeSlide 23Observer (Publish - Subscribe)Observer (Publish - Subscribe)Slide 26Slide 27Observer (Publish - Subscribe)Takeaways from Chapter 26Next …Object-Oriented Analysis and DesignCHAPTER 26: GOF DESIGN PATTERNS1What will we learn?We will conclude our introduction to the Gang of Four (GoF) Patterns23 1PricingStrategyFactoryinstance : PricingStrategyFactorygetInstance() : PricingStrategyFactorygetSalePricingStrategy() : ISalePricingStrategygetSeniorPricingStrategy() : ISalePricingStrategy...{ String className = System.getProperty( "salepricingstrategy.class.name" ); strategy = (ISalePricingStrategy) Class.forName( className ).newInstance(); return strategy; }4:Sale1:PricingStrategyFactoryps =getSalePricingStrategy:RegistermakeNewSalecreatecreate(percent)ps : PercentDiscountPricingStrategyNeed to get Fac instance firstComposite Recall the pricing strategy problem we studied last time: How to apply a pricing strategy to the POS total Sale, when the strategy may be changing from time to timeThe solution was to use the Strategy pattern, which essentially used polymorphism to define objects for the strategies, and a factory to create the objectsThe Sale object then retrieved the pricing strategy object from the factory, and (using an interface reference) was able to apply the pricing strategy This way, the logic behind the algorithm of the pricing strategy was completely hidden from the Sale object – it was kept in the strategy objects, where it belongs – keeping the Sale object simpler What if we have multiple, competing pricing strategies?There may be several pricing strategies in play – which one to apply? The store needs a “conflict resolution” strategy – something like “choose the discount that gives the lowest price to the customer”5Composite We don’t want the Sale to be aware of the different (competing) strategies – remember, the Sale should just do its job and not worry about the pricing logic We could have the factory object do this (since it is aware of the strategy objects), but that would complicate the factory object’s logic and make it complex The best way to handle this is to create a new object that will be responsible for knowing all of the pricing strategies and also contain the logic to decide which one to apply Problem: How to treat a group or composition structure of objects the same way (polymorphically) as a non-composite (atomic) object? Solution: Define classes for composite and atomic objects so that they implement the same interface6Composite In the case of the POS system, we could create a new class called CompositeBestForCustomerPricingStrategy which implements the ISalesPricingStrategy interface and also contains a list of the ISalesPricingStrategies objectsThis is common in Composite objects: They implement the interface, but also contain a list of the (“inner”) interface objects, so they iterate over them and choose one based upon some logic Notice that since the composite object implements the interface, the composite object may be attached to the Sale objectThe Sale object can use the atomic strategy (e.g. PercentDiscountPricingStrategy) or the composite – both implement the interface, so both understand the getTotal() message. We can even extend, by defining a general (abstract) CompositePricingStrategy superclass (that implements the interface and maintains the list of strategies) and then have sub-classes for different Composites … see next slides for full design78PercentageDiscountPricingStrategypercentage : floatgetTotal( Sale ) : MoneyAbsoluteDiscountOverThresholdPricingStrategydiscount : Moneythreshold : MoneygetTotal( Sale ) : Money«interface»ISalePricingStrategygetTotal( Sale ) : Money{ return sale.getPreDiscountTotal() * percentage }CompositePricingStrategyadd( ISalePricingStrategy )getTotal( Sale ) : Money{lowestTotal = INTEGER.MAXfor each ISalePricingStrategy strat in pricingStrategies { total := strat.getTotal( sale ) lowestTotal = min( total, lowestTotal ) }return lowestTotal }1..*CompositeBestForCustomerPricingStrategygetTotal( Sale ) : MoneyCompositeBestForStorePricingStrategygetTotal( Sale ) : MoneystrategiesAll composites maintain a list of contained strategies. Therefore, define a common superclass CompositePricingStrategy that defines this list (named strategies). Saledate...getTotal()...1pricingStrategy{...return pricingStrategy.getTotal( this )}9:CompositeBestForCustomerPricingStrategys : Salest = getSubtotalt = getTotallineItems[ i ] :SalesLineItemt = getTotal( s )the Sale object treats a Composite Strategy that contains other strategies just like any other ISalePricingStrategyx = getTotal( s )strategies[ j ] :: ISalePricingStrategyUML: 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) }looploopComposite public abstract class CompositePricingStrategy implements ISalePricingStrategy{ protected List strategies = new ArrayList(); public add(ISalePricingStrategy s) { strategies.add(s); } public abstract Money getTotal(Sale sale);}10Composite public class CompositeBestForCustomerPricingStrategy extends CompositePricingStrategy{ public Money getTotal(Sale sale) {Money lowestTotal = new Money(Integer.MAX_VALUE);for(Iterator i = strategies.iterator(); i.hasNext();){ ISalePricingStrategy strategy = (ISalePricingStrategy)i.next(); Money total = strategy.getTotal(sale); lowestTotal = total.min(lowestTotal);} return lowestTotal; }}1112CompositePricingStrategyadd( ISalePricingStrategy )getTotal( Sale ) : MoneyCompositeBestForCustomerPricingStrategygetTotal( Sale ) : MoneyCompositeBestForStorePricingStrategygetTotal( Sale ) : MoneyUML notation: An abstract class is shown with an italicized nameabstract methods are also shown with italicsComposite How to create multiple pricing strategies? In particular, when do we create the strategies that make up the composite? Best approach would be to create a “default” strategy ( it may do nothing, or provide for a 0% discount, initially)As more strategies are created, they can be added to the composite Consider three ways to add new strategies:Initial store-defined strategy,
View Full Document