440 likes | 463 Views
Introduction to Design Patterns. Design Patterns can be simple…. Highlighting a SHAPE in a GUI application Possible solution: Each class, such as CAR, HOUSE implements a method called highlight Problem: Inconsistent Solution: In class SHAPE:. public void highlight(…) { translate(1,1);
E N D
Design Patterns can be simple… • Highlighting a SHAPE in a GUI application • Possible solution: Each class, such as CAR, HOUSE implements a method called highlight • Problem: Inconsistent • Solution: In class SHAPE: public void highlight(…) { translate(1,1); draw(); translate(1,1); draw(); translate(-2,-2); } COSC6431
Template Method COSC6431
Context An algorithm is applicable for multiple types The algorithm can be broken down into primitive operations that may be different for each type The order of the primitive operations does not depend on the type Solution Define an abstract superclass with a method for the algorithm and abstract methods for the primitive operations Algorithm calls primitive operations in right order Each subclass implements primitive operations but not the algorithm Template Method COSC6431
DPs can be language dependent • Singleton pattern: A particular class must have only one instance. This instance may be shared across the system. public class Singleton { // Java private Singleton() {…} public static Singleton getSingleton() { if (instance == null) instance = new Singleton(); return instance; } private static Singleton instance; } What about threads? Cloning? COSC6431
CLIENT SINGLETON_ACCESSOR SINGLETON Scenario: Get instance Request the_instance Create the_instance(only once) Singleton Pattern in Eiffel Eiffel has once functions but no static variables 1 2 COSC6431
Singleton Accessor Class class SINGLETON_ACCESSOR feature the_instance: SINGLETON is -- Create the only instance in the system once create Result.make(…) end end COSC6431
Single Instance Class class SINGLETON creation {SINGLETON_ACCESSOR} make feature make is do …. end end COSC6431
Most design patterns are… • More involved • A larger number of classes and objects take part • Language independent • The pattern concept can be implemented in any OO language • Let’s look at some examples… COSC6431
Observer Pattern • Intent • Define one-to-many dependency • When one subject changes state, all observers (dependents) are notified and correspondingly updated • Also known as • Dependents and Publish-Subscribe COSC6431
Observer – Motivation text view A is 30% B is 50% C is 20% Notify change Request modification target view bar view rectangle view COSC6431
Observer Architecture OBSERVER * SUBJECT observers : set[…] update * attach(observer) detach(observer) notify TARGET_VIEW + subject update + TEXT_VIEW BAR_VIEW + get_state set_state subject update + subject RECTANGLE_VIEW + update + COSC6431
Observer – Participants • Subject • Knows its observers • Provides interface for attaching, detaching and notifying its observers • Observer • Defines an updating interface for observers COSC6431
Observer – Participants – 2 • Concrete subject • Stores state of interest to concrete observers • Notifies observers when state changes • Concrete observer • Maintains a reference to its concrete subject • Stores state that corresponds to the state of the subject • Implements Observer updating interface COSC6431
Scenario: Update observers 1 set_state 2 notify 3 update 4 get_state Observer – Scenario • Concrete subject updates all observers, when state is changed by a client CLIENT 2 1 CONCRETE_SUBJECT 4 3 CONCRETE_OBSERVER COSC6431
Observer – Consequences – 1 • Abstract coupling between subject and observer • Permits changing number of observers dynamically • Supports broadcast communication • Can have observers depend upon more than one subject COSC6431
Observer – Consequences – 2 • Need additional protocol to indicate what changed • Can have spurious updates • Not all observers participate in all changes • Dangling references when subject is deleted • Notify observers when subject is deleted • Not an issue in an environment with garbage collection COSC6431
Composite Pattern • Intent • Compose objects into tree structures representing part-whole hierarchies • Clients deal uniformly with individual objects and hierarchies of objects COSC6431
Composite – Motivation • Applications that have recursive groupings of primitives and groups • Drawing programs lines, text, figures and groups • Containment structure Subsystems and files • Operations on groups are different than primitives but users treat them in the same way COSC6431
DIAGRAM DIAGRAM DIAGRAM DIAGRAM TEXT LINE OVAL OVAL TEXT TEXT Composite – Drawing Example COSC6431
CLIENT COMPOSITE[T] * GRAPHIC * add * remove * iterate * draw * DIAGRAM + draw + add + remove + iterate + Composite Architecture T TEXT + OVAL + LINE + draw + draw + draw + COSC6431
Composite – Applicability • Represent part-whole hierarchies of objects • Clients can ignore difference between individual objects and compositions • Clients deal with all objects in a composition in the same way COSC6431
Composite – Consequences • Whenever client expects a primitive it can accept a composite • Client is simplified by removing tag-case statements to identify parts of the composition • Easy to add new components by subclassing, client does not change • If compositions are to have restricted sets of components have to rely on run-time checking COSC6431
Decorator Pattern • Intent • Attach additional responsibilities to an object dynamically. • Provide a flexible alternative to subclassing for extending functionality COSC6431
Decorator – Motivation • Motivation – Applicability • Want to add responsibility to individual objects not to entire classes • Add properties like border, scrolling, etc to any user interface component as needed • Enclose object within a decorator object for flexibility • Nest recursively for unlimited customization COSC6431
Decorator – Example • Compose a border decorator with a scroll decorator for text view. a_border_decorator component a_scroll_decorator component a_text_view COSC6431
Decorator – Example Diagram VISUAL_COMPONENT * draw * DECORATOR * TEXT_VIEW + draw component : VISUAL_ COMPONENT BORDER_DECORATOR + SCROLL_DECORATOR + draw border_width draw_border draw scroll_position scroll_to COSC6431
Decorator – Applicability • Add responsibilities to individual objects dynamically and transparently • Without affecting other objects • For responsibilities that can be withdrawn • When subclass extension is impractical • Sometimes a large number of independent extensions are possible • Avoid combinatorial explosion • Class definition may be hidden or otherwise unavailable for subclassing COSC6431
Decorator – General Structure COMPONENT * method * CONCRETE_COMPONENT + DECORATOR * component : COMPONENT method CONCRETE_DECORATOR_B + CONCRETE_DECORATOR_ A + method another_feature method other_feature COSC6431
Decorator – Participants • Component • defines the interface for objects that can have responsibilities added to them dynamically • Concrete component • Defines an object to which additional responsibilities can be attached • Decorator • Maintains a reference to a component object and defines an interface that conforms to COMPONENT • Concrete decorator • Add responsibilities to the component COSC6431
Decorator – Consequences • Benefits • More flexibility than static inheritance • Can add and remove responsibilities dynamically • Can handle combinatorial explosion of possibilities • Avoids feature laden classes high up in the hierarchy • Pay as you go when adding responsibilities • Can support unforeseen features • Decorators are independent of the classes they decorate • Functionality is composed in simple pieces COSC6431
Decorator – Consequences – 2 • Liabilities • From object identity point of view, a decorated component is not identical • Decorator acts as a transparent enclosure • Cannot rely on object identity when using decorators • Lots of little objects • Often result in systems composed of many look alike objects • Differ in the way they are interconnected, not in class or value of variables • Can be difficult to learn and debug COSC6431
Visitor Pattern • Intent • Represent an operation to be performed on all of the components of an object structure • Define new operations on a structure without changing the classes representing the components COSC6431
Visitor – Motivation • Representing computer equipment EQUIPMENT * Operations spread out OO style but ... difficult to add a new operation describe * price * COMPOSITE_EQUIPMENT + FLOPPY_DISK + .... describe + price + describe + price + COSC6431
Visitor Architecture • Equipment classes are independent of the operations • Equipment accept visitors and direct them to the appropriate operation – through polymorphism * EQUIPMENT_VISITOR * EQUIPMENT accept + PRICING_VISITOR + CHASSIS accept visit_chassis One subclass of EQUIPMENT_VISITOR for each operation One subclass of EQUIPMENT for each concrete piece of equipment COSC6431
Visitor – Applicability • Object structure contains many classes of objects with differing interfaces and want to perform operations that depend on their concrete classes • Many distinct and unrelated operations need to be performed • Do not want to or are unable to clutter the concrete classes with these operations • Keep the related operations together, e.g. operations on pricing various types of EQUIPMENT are all in the PRICING_VISITOR class • If the object structure is shared by many applications, Visitor puts operations into only those applications that need them COSC6431
Visitor – Applicability – 2 • The classes defining the object structure rarely change, but you often want to define new operations over the structure Changing object structure means redefining interface to all visitors, which is costly If object structure changes often, Visitor is inappropriate COSC6431
ELEM_B + Visitor – Abstract Architecture VISITOR * ELEMENT * accept ( VISITOR ) * ... visit_elem_A ( ELEM_A ) * visit_elem_B ( ELEM_B ) * ... ELEM_A + CONCRETE_VISITOR_1 + accept ( VISITOR ) + ... visit_elem_A ( ELEM_A ) + visit_elem_B ( ELEM_B ) + ... CONCRETE_VISITOR_2 + COSC6431
Visitor – Participants • Element Declares accept method that takes a visitor as an argument • Concrete element Implements the accept method • Visitor Declares a visit operation for each concrete element class COSC6431
Visitor – Participants – 2 • Concrete visitor • Implements every visit operation declared in Visitor Each visit operation implements a fragment of the algorithm defined for the concrete visitor • Provides the context for the algorithm composed of all of the visit fragments State accumulates with each visit • Implements the high level organization • Iteration over the components • Processing each in turn COSC6431
MAIN 1 2 CABINET PRICING_VISITOR 3 4 CHASSIS Visitor – Scenario • A pricing visitor visits a composite equipment • For each equipment, the pricing visitor selects which method from the EQUIPMENT_VISITOR interface to execute Scenario: Visit a cabinet 1 Accept the pricing visitor 2 visit_cabinet 3 visit_children 4 Accept the pricing visitor COSC6431
Visitor – Consequences • Adding new operations is easy • New operation implements the Visitor interface, e.g. the methods in EQUIPMENT_VISITOR • All the fragments of the visitor algorithm are in one file – related behaviours are together Easier to make sure that elements are working in unison • Unrelated operations and fragments are in other visitor classes • Contrast with having to change each of the concrete element classes to have the operation fragment Each class has a fragment of each of the operations COSC6431
Visitor – Consequences – 2 • Adding new concrete elements is difficult • Need to modify the Visitor interface • Need to modify each concrete visitor • Can sometimes simplify as many elements have common behaviour (default behaviour) that can be specified at concrete visitor level 1. • Create subclasses of level 1 for more specific behaviour for the new elements • Only program the new elements • For many structures elements do not change rapidly so this is not a problem COSC6431
Visitor – Consequences – 3 • One can visit object structures composed of unrelated objects • The various visit_* methods do not have to take arguments that are related • The main difference between Visitor and Iterator • State accumulation • Visitors contain data structures related to the operation they implement, e.g. the PRICING_VISITOR contains the total price • Without a visitor, such data would have to be passed as arguments (or become global variables) COSC6431