SOEN 6011 Software Engineering Processes Section SS Fall 2007 Dr Greg Butler http://www.cs.concordia.ca/~gregb/home/soen6011-f2007.html Week 9 • Design patterns Gang Of Four • Gamma, Helm, Johnson, Vlissides • Some patterns in Larman, Chap. 23,… • All patterns in XDE – As documentation. – As dynamic templates. Overview of Patterns •Present solutions to common software problems arising within a certain context •Help resolve key software design forces •Capture recurring structures & dynamics among software participants to facilitate reuse of successful designs •Generally codify expert knowledge of design strategies, constraints & “best practices” AbstractService service Client Proxy service Service 1 1 service The Proxy Pattern •Flexibility •Extensibility •Dependability •Predictability •Scalability •Efficiency Design – Repeat Successes • Has a (successful) similar product been built? • Yes, then reuse domain specific: – Architectural • Style (e.g. client/server, database, process control) • Patterns. – Design Patterns (& idioms). • Use Domain model as source of inspiration. Design – New Application Area? • Has a (successful) similar product been built? • No, then choose among general: – Architectural • Style (e.g. client/server, database, process control) • Patterns. – Design Patterns (& idioms). • Use Domain model as source of inspiration. GoF Pattern Classification • Behavioral Patterns • Creational Patterns • Structural Patterns GoF Pattern Summary & Relationships GoF Behavioral Patterns • Chain of Responsibility • Command • Interpreter • Iterator • Mediator • Memento • • • • • Observer State Strategy Template Method Visitor GoF Creational Patterns • • • • • Abstract Factory Builder Factory Method Prototype Singleton GoF Structural Patterns • • • • • • • Adapter Bridge Composite Decorator Facade Flyweight Proxy Command Pattern (for Front Controller) Problem: How to allow the same command to be invoked by – Menu selection – Alt-ctrl shortcut – Commandline text entry, etc • How to allow (unlimited) undo/redo • How to keep a log/audit/history of commands invoked • How to allow “macro” commands to be defined Command Pattern (for Front Controller) • You have commands that need to be – executed, – undone, or – queued • Command design pattern separates – Receiver from Invoker from Commands • All commands derive from Command and implement do(), undo(), and redo() • Also allows recording history, replay Adapter • Context / 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. Adapter • Suppose we have a tax calculation class (or external library) but the interface is not well suited for our application. GoodAsGoldTaxPro +computeTax() : double Adapter • Adapter provides an interface suited to the application GoodAsGoldTaxProAdapter getTaxes( Sale ) : List of TaxLineItems GoodAsGoldTaxPro computeTax(…):double Adapter (For More than One Class) • What if more than one class (library) needs to be adapted? «interface» ITaxCalculatorAdapter Adapter getTaxes( Sale ) : List of TaxLineItems TaxMasterAdapter GoodAsGoldTaxPro Adapter getTaxes( Sale ) : List of TaxLineItems getTaxes( Sale ) : List of TaxLineItems * * GoodAsGoldTaxPro +computeTax() : double Singleton Pattern Notice: • Constructor is no longer public. • To access the instance use getUniqueInstance(). • All other attribute and method declarations of C stay the same. «Singleton» C - attribute1 - attribute2_etc - uniqueInstance : C -C( ) + getUniqueInstance ( ) + methodA ( ) + methodB_etc ( ) Facade Facade Factory • Context / problem: Who should be responsible for creating objects when there are special considerations, such as complex creation logic, a desire to separate the creation responsibilities for better cohesion, and so forth? • Solution: Create a Pure Fabrication object called a Factory. (Abstract) Factory Example (GoF) Factory (in EAs) FrontCommand FrontControllerServlet # processRequest ( ) - getCommand ( ) : FrontCommand - getCommandClass ( ) + init ( ) + processRequest ( ) RemoveStudentCommand + processRequest ( ) ViewStudInfoCommand + processRequest ( ) Strategy • Context / problem: How to design for varying, but related, algorithms or policies? How to design for the ability to change (even dynamically) these algorithms or policies? • Solution: Define each algorithm/policy/strategy in a separate class with a common interface Strategy PercentDiscount PricingStrategy «interface» ISalePricingStrategy getTotal( Sale ) : Money AbsoluteDiscount OverThreshold PricingStrategy percentage : float getTotal( s:Sale ) : Money discount : Money threshold : Money getTotal( s:Sale ) : Money { return s.getPreDiscountTotal() * percentage } { pdt := s.getPreDiscountTotal() if ( pdt < threshold ) return pdt else return pdt - discount } How Do We Create a Strategy? 1 PricingStrategyFactory instance : PricingStrategyFactory getInstance() : PricingStrategyFactory getSalePricingStrategy() : ISalePricingStrategy getSeniorPricingStrategy() : ISalePricingStrategy ... { String className = System.getProperty( "salepricingstrategy.class.name" ); strategy = (ISalePricingStrategy) Class.forName( className ).newInstance(); return strategy; } Composite (Larman05, 26.8) Context/problem • How do you treat a group or composite 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 interface. Composite: Ex. Class Diagram Composite: Ex. Objects Must “add” be implemented by Line? • In C++ add declared virtual; subclass need not implement it. • In Java if add is abstract, then subclasses must implement it. String add(Graphic g) { throw new UnsupportedOperationException(); } • Can you think of a better solution? Composite: Clients point-of-view { ... return pricingStrategy.getTotal( this ) } Sale date ... getTotal() ... * 1 «interface» ISalePricingStrategy getTotal( Sale ) : Money 1..* pricingStrategies Composite Pricing Strategies • Interface • Realization PercentageDiscount PricingStrategy «interface» ISalePricingStrategy getTotal( Sale ) : Money AbsoluteDiscount OverThreshold PricingStrategy 1..* pricingStrategies Composite PricingStrategy percentage : float getTotal( Sale ) : Money discount : Money threshold : Money getTotal( Sale ) : Money add( ISalePricingStrategy ) getTotal( Sale ) : Money Observer Pattern Goal: When the total of the sale changes, refresh the display with the new value Sale total ... setTotal( newTotal ) ... Observer • How shall we have the display be updated? • Why not … have the Sale inform the display when it changes value. What is Wrong With This? update( ) Sale total ... setTotal( newTotal ) ... Observer Pattern • Context / Problem: Different kinds of subscriber objects are interested in the state changes or events of a publisher object, and want to react in their own way when the publisher generates the event. … Observer Pattern • Solution: Define a “subscriber” or “listener” interface. Subscribers implement this interface. The publisher can dynamically register subscribers who are interested in an event, and notify them when an event occurs. • Clarification: Publisher can dynamically process registration requests from subscribers. Observer Pattern (GoF book) Observers: Illustration