object oriented patterns frameworks
play

Object-Oriented Patterns & Frameworks Dr. Douglas C. Schmidt - PowerPoint PPT Presentation

Object-Oriented Patterns & Frameworks Dr. Douglas C. Schmidt d.schmidt@vanderbilt.edu www.dre.vanderbilt.edu/ ~schmidt Professor of E E CS Vanderbilt University Nashville, Tennessee Pattern & Framework Tutorial Douglas C. Schmidt


  1. Pattern & Framework Tutorial Douglas C. Schmidt Overview of Frameworks • Frameworks exhibit • Frameworks provide • Frameworks are “inversion of control” at integrated domain-specific “semi-complete” runtime via callbacks structures & functionality applications Application-specific functionality Scientific Mission Visualization Computing E-commerce GUI Networking Database 21

  2. Pattern & Framework Tutorial Douglas C. Schmidt Motivation for Frameworks Air Air GPS AP HUD Frame Nav Nav Nav Nav HUD HUD HUD Frame Air AP AP AP FLI R FLI R FLI R FLI R Frame Air I FF GPS GPS I FF GPS I FF I FF Frame Cyclic Cyclic Cyclic Cyclic Exec Exec Exec Exec UCAV F/ A-18 A/ V-8B F-15 Legacy embedded systems have Consequence: Small historically been: HW/SW changes have • Stovepiped big (negative) impact • Proprietary on system QoS & • Brittle & non-adaptive maintenance • Expensive • Vulnerable 22

  3. Pattern & Framework Tutorial Douglas C. Schmidt Motivation for Frameworks F/ A 18 A/ V 8-B product product UCAV variant variant product F-15 Air variant product FLI R Frame AP variant HUD GPS Nav I FF Domain-specific Services Common Middleware Services Distribution Middleware Host I nfrastructure Middleware Product-line OS & Network Protocols architecture Hardware (CPU, Memory, I / O) • Fra ram ew ork rks factors out many reusable general-purpose & domain-specific services from traditional DRE application responsibility • Essential for pr produ duct -line arch chit ect ct ures ( PLAs) • Product-lines & frameworks offer many configuration opportunities • e.g., component distribution/deployment, OS, protocols, algorithms, etc. 23

  4. Pattern & Framework Tutorial Douglas C. Schmidt Categories of OO Frameworks • White-box frameworks are reused by subclassing, which usually requires understanding the implementation of the framework to some degree • Black-box framework is reused by parameterizing & assembling framework objects, thereby hiding their implementation from users • Each category of OO framework uses different sets of patterns, e.g.: – Black-box frameworks reply heavily on object composition patterns, such – White-box frameworks rely heavily as Strategy & Decorator on inheritance-based patterns, such as Template Method & State 24 Many frameworks fall in between white-box & black-box categories

  5. Pattern & Framework Tutorial Douglas C. Schmidt Commonality & Variability Analysis in Frameworks • Framework characteristics • Applying SCV to avionics mission computing are captured via Scope, • Scope defines the domain & context of Commonalities, & the framework Variabilities (SCV) analysis • Component architecture, object- • This process can be oriented application frameworks, & applied to identify associated components, e.g., GPS, commonalities & Airframe, & Display variabilities in a domain Reusable Application to guide development of Components a framework Air FLI R Frame AP HUD GPS Nav Reusable Architecture I FF Framework Domain-specific Services Common Middleware Services Distribution Middleware Host I nfrastructure Middleware OS & Network Protocols 25

  6. Pattern & Framework Tutorial Douglas C. Schmidt Applying SCV to an Avionics Framework • Com m onalit ies describe the attributes that are common across all members of the framework • Common object-oriented frameworks & set of component types • e.g., GPS, Airframe, Navigation, & Display components • Common middleware infrastructure GPS Navigation Airframe Heads Up • e.g., Real-time Component Component Component Display CORBA & a variant of Lightweight CORBA Component Common Components Model (CCM) called Domain-specific Services Prism Common Middleware Services Distribution Middleware Host I nfrastructure Middleware OS & Network Protocols Hardware (CPU, Memory, I / O) 26

  7. Pattern & Framework Tutorial Douglas C. Schmidt Applying SCV to an Avionics Framework • Vari riabilit ies describe the GPS Display Airframe Heads Up attributes unique to the Component Component Component Display different members of the framework Common Components • Product-dependent component GPS = 40 Hz GPS=20Hz GPS = 20 Hz Air Air Fram Air GPS implementations (GPS/INS) Fram Nav Frame Nav Nav HUD HUD Nav e AP e HUD AP AP FLIR FLIR AP FLIR FLIR • Product-dependent IF IF GPS GPS IFF IFF HUD F GPS F component connections F/A 18 F F 15K UCAV • Product-dependent component assemblies (e.g., different weapons systems for different customers/countries) Domain-specific Services Common Middleware Services • Different hardware, OS, & Distribution Middleware network/bus configurations Host I nfrastructure Middleware OS & Network Protocols Hardware (CPU, Memory, I / O) 27

  8. Pattern & Framework Tutorial Douglas C. Schmidt Comparing Reuse Techniques LOCAL Class Library (& STL) Architecture APPLICATION- INVOCATIONS Math SPECIFIC IPC FUNCTIONALITY ADTs • A class is an implementation unit in an OO Files programming language, i.e., a reusable t ype e Strings GUI that often implements pat t e t t erns GLUE EVENT Locks CODE LOOP • Classes in class libraries are typically passive NETWORKI NG Framework Architecture Reactor ADTs • A fra ram ew ork rk is an integrated set of Strings APPLI CATI ON- classes that collaborate to form a reusable SPECI FI C I NVOKES CALL GUI FUNCTI ONALI TY BACKS architecture for a family of applications Files Locks • Frameworks implement pat t e t t ern DATABASE langu guage ges Component & Service-Oriented Architecture Naming Events • A com om pon onent is an encapsulation unit with one or more interfaces that provide clients with access to its services Logging Locking • Components can be deployed & configured 28 Middleware Bus via assem ssem blies es

  9. Pattern & Framework Tutorial Douglas C. Schmidt Taxonomy of Reuse Techniques Class Frameworks Components Libraries Micro-level Meso-level Macro-level “Semi- Stand-alone Stand-alone complete” composition entities language entities applications Domain- Domain-specific Domain-specific or independent Domain-independent Borrow caller’s Inversion of Borrow caller’s thread control thread 29

  10. Pattern & Framework Tutorial Douglas C. Schmidt Benefits of Frameworks • Design reuse AdminClient PickingClient • e.g., by guiding application Admin Admin Picking Picking Controllers Views Controllers Views developers through the steps Thin UI Clients necessary to ensure successful Proxy Proxy creation & deployment of software Broker Broker OS-Access Component Layer Repository Distribution Communication Component Infrastructure Services Configurator Broker Broker Scheduler/ Reactor ActivationList Service Request Logging ThreadPool Handler * Service Service Request Request Concurrency Infrastructure WarehouseRepHalfX 30

  11. Pattern & Framework Tutorial Douglas C. Schmidt Benefits of Frameworks • Design reuse package org.apache.tomcat.session; import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; import java.io.*; • e.g., by guiding application import java.net.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; developers through the steps /** * Core implementation of a server session * necessary to ensure successful * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] */ creation & deployment of software public class ServerSession { private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); • I mplementation reuse private Hashtable values = new Hashtable(); private Hashtable appSessions = new Hashtable(); private String id; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; • e.g., by amortizing software private int inactiveInterval = -1; ServerSession(String id) { this.id = id; lifecycle costs & leveraging } public String getId() { return id; previous development & } public long getCreationTime() { return creationTime; optimization efforts } public ApplicationSession getApplicationSession(Context context, boolean create) { ApplicationSession appSession = (ApplicationSession)appSessions.get(context); if (appSession == null && create) { // XXX // sync to ensure valid? appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); } // XXX // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate & create // a new appSession return appSession; } void removeApplicationSession(Context context) { appSessions.remove(context); } 31

  12. Pattern & Framework Tutorial Douglas C. Schmidt Benefits of Frameworks • Design reuse • e.g., by guiding application developers through the steps necessary to ensure successful creation & deployment of software • I mplementation reuse • e.g., by amortizing software lifecycle costs & leveraging previous development & optimization efforts • Validation reuse • e.g., by amortizing the efforts of validating application- & platform- independent portions of software, thereby enhancing software reliability & scalability 32

  13. Pattern & Framework Tutorial Douglas C. Schmidt Limitations of Frameworks • Frameworks are powerful, but can be hard to use effectively (& even harder to create) for many application developers • Commonality & variability analysis requires significant domain knowledge & OO design/implementation expertise • Significant time required to evaluate applicability & quality of a framework for a particular domain • Debugging is tricky due to inversion of control • V&V is tricky due to “late binding” • May incur performance degradations due to extra (unnecessary) levels of indirection www.cs.wustl.edu/ ~schmidt/PDF/Queue-04.pdf Many frameworks limitations can be addressed with knowledge of patterns! 33

  14. Pattern & Framework Tutorial Douglas C. Schmidt Using Frameworks Effectively Observations • Since frameworks are powerful—but but hard to develop & use effectively by application developers—it’s often better to use & customize COTS frameworks than to develop in-house frameworks • Classes/components/services are easier for application developers to use, but aren’t as powerful or flexible as frameworks Successful projects are therefore often organized using the “funnel” model 34

  15. Pattern & Framework Tutorial Douglas C. Schmidt Stages of Pattern & Framework Awareness 35

  16. Pattern & Framework Tutorial Douglas C. Schmidt Part II: Case Study: Expression Tree Application Goals • Develop an object-oriented expression tree evaluator program using patterns & frameworks • Demonstrate commonality/variability analysis in the context of a concrete application example Binary • Illustrate how OO frameworks can be Nodes combined with the generic programming features of C+ + & STL • Compare/contrast OO & non-OO approaches Unary Node Leaf Nodes 36

  17. Pattern & Framework Tutorial Douglas C. Schmidt Overview of Expression Tree Application • Expression trees consist of nodes containing operators & operands • Operators have different precedence levels, different associativities, & different arities, e.g.: • Multiplication takes precedence over addition • The multiplication operator has two Binary Nodes arguments, whereas unary minus operator has only one • Operands can be integers, doubles, variables, etc. Unary • We'll just handle integers in this Node application • Application can be extended easily Leaf Nodes 37

  18. Pattern & Framework Tutorial Douglas C. Schmidt Overview of Expression Tree Application • Trees may be “evaluated” via different traversal orders • e.g., in-order, post-order, pre-order, level-order • The evaluation step may perform various operations, e.g.: • Print the contents of the expression tree Binary • Return the “value" of the expression tree Nodes • Generate code • Perform semantic analysis & optimization Unary • etc. Node Leaf Nodes 38 See tree-traversal example

  19. Pattern & Framework Tutorial Douglas C. Schmidt Using the Expression Tree Application • By default, the expression tree application can run in “succinct mode,” e.g.: % tree-traversal > 1+ 4* 3/2 7 % tree-traversal -v > (8/4) * 3 + 1 format [in-order] 7 expr [expression] ^ D print [in-order|pre-order|post-order|level-order] eval [post-order] • You can also run quit the expression > format in-order tree application > expr 1+ 4* 3/2 in “verbose > eval post-order mode,” e.g.: 7 > quit 39

  20. Pattern & Framework Tutorial Douglas C. Schmidt How Not to Design an Expression Tree Application A typical algorithmic-based solution for implementing expression trees uses a C struct/union to represent the main data structure typedef struct Tree_Node { enum { NUM, UNARY, BINARY } tag_; short use_; /* reference count */ union { char op_[2]; int num_; } o; #define num_ o.num_ #define op_ o.op_ union { struct Tree_Node *unary_; struct { struct Tree_Node *l_, *r_;} binary_; } c; #define unary_ c.unary_ #define binary_ c.binary_ } Tree_Node; 40

  21. Pattern & Framework Tutorial Douglas C. Schmidt How Not to Design an Expression Tree Application Here’s the memory layout & class diagram for a struct Tree_Node : 41

  22. Pattern & Framework Tutorial Douglas C. Schmidt How Not to Design an Expression Tree Application A typical algorithmic implementation uses a switch statement & a recursive function to build & evaluate a tree, e.g.: void print_tree (Tree_Node *root) { switch (root->tag_) case NUM: printf (“%d”, root->num_); break; case UNARY: printf ("(%s”, root->op_[0]); print_tree (root->unary_); printf (")"); break; case BINARY: printf ("("); print_tree (root->binary_.l_); // Recursive call printf (“%s”, root->op_[0]); print_tree (root->binary_.r_); // Recursive call printf (")"); break; default: printf ("error, unknown type "); } 42

  23. Pattern & Framework Tutorial Douglas C. Schmidt Limitations with the Algorithmic Approach • Little or no use of encapsulation: • Data structures are “passive” implementation details available to functions that do their work clients explicitly • Incomplete modeling of the • The program organization makes it application domain, which results in hard to extend • Tight coupling between • e.g., Any small changes will nodes/edges in union ripple through entire representation design/implementation • Complexity being in algorithms • Easy to make mistakes switching rather than the data structures, on type tags e.g., switch statements are used to • Wastes space by making worst- select between various types of case assumptions wrt structs & nodes in the expression trees unions 43

  24. Pattern & Framework Tutorial Douglas C. Schmidt An OO Alternative Using Patterns & Frameworks • Start with OO modeling of the “expression tree” application domain Binary Nodes • Model a tree as a collection of nodes • Nodes are represented in an inheritance hierarchy that captures the particular properties Unary Node of each node • e.g., precedence levels, different associativities, & different arities Leaf Nodes • Conduct commonality/variability analysis (CVA) to determine stable interfaces & points of variability • Apply patterns to guide design/implementation of framework • Integrate with C+ + STL algorithms/containers where appropriate 44

  25. Pattern & Framework Tutorial Douglas C. Schmidt Design Problems & Pattern-Oriented Solutions Design Problem Pattern(s) Binary Expression tree structure Composite Nodes Encapsulating variability & Bridge simplifying memory management Unary Tree printing & evaluation Iterator & Visitor Node Consolidating user Command operations Leaf Ensuring correct protocol State Nodes for commands Consolidating creation of Abstract Factory Variabilities & Factory Method Parsing expressions & Interpreter & creating expression tree Builder 45

  26. Pattern & Framework Tutorial Douglas C. Schmidt Design Problems & Pattern-Oriented Solutions Design Problem Pattern(s) Binary Driving the application Reactor Nodes event flow Supporting multiple Template Method operation modes & Strategy Unary Centralizing global Singleton Node objects effectively Implementing STL Prototype Leaf iterator semantics Nodes Eliminating loops via the Adapter STL std::for_each() algorithm Provide no-op commands Null Object None of these patterns are restricted to expression tree applications… 46

  27. Pattern & Framework Tutorial Douglas C. Schmidt Managing Global Objects Effectively Goals: Verbose mode % tree-traversal -v – Centralize access to format [in-order] objects that should be expr [expression] visible globally, e.g.: print [in-order|pre-order|post-order|level-order] – command-line options eval [post-order] that parameterize the quit behavior of the program > format in-order – The object (Reactor) > expr 1+ 4* 3/2 that drives the main > eval post-order event loop 7 Constraints/ forces: > quit – Only need one instance Succinct mode of the command-line % tree-traversal options & Reactor > 1+ 4* 3/2 – Global variables are 7 problematic in C+ + 47

  28. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Centralize Access to Global Instances Rather than using global variables, create a central access point to global instances, e.g.: int main (int argc, char *argv[]) { // Parse the command-line options. if (!Options::instance ()->parse_args (argc, argv)) return 0; // Dynamically allocate the appropriate event handler // based on the command-line options. Expression_Tree_Event_Handler *tree_event_handler = Expression_Tree_Event_Handler::make_handler (Options::instance ()->verbose ()); // Register event handler with the reactor. Reactor::instance ()->register_input_handler (tree_event_handler); // ... 48

  29. Pattern & Framework Tutorial Douglas C. Schmidt Singleton object creational I ntent ensure a class only ever has one instance & provide a global point of access Applicability – when there must be exactly one instance of a class, & it must be accessible from a well-known access point – when the sole instance should be extensible by subclassing, & clients should be able to use an extended instance without modifying their code Structure If (uniqueInstance == 0) uniqueInstance = new Singleton; return uniqueInstance; 49

  30. Pattern & Framework Tutorial Douglas C. Schmidt Singleton object creational Consequences Known Uses + reduces namespace pollution – Unidraw's Unidraw object + makes it easy to change your mind & – Smalltalk-80 ChangeSet, allow more than one instance the set of changes to code + allow extension by subclassing – InterViews Session object – same drawbacks of a global if misused See Also – implementation may be less efficient – Double-Checked Locking than a global Optimization pattern from – concurrency pitfalls strategy creation & POSA2 communication overhead – “To Kill a Singleton” I mplementation www.research.ibm.com/ designpatterns/pubs/ – static instance operation ph-jun96.txt – registering the singleton instance – deleting singletons 50

  31. Pattern & Framework Tutorial Douglas C. Schmidt Expression Tree Structure Goals: – Support “physical” structure of expression tree • e.g., binary/unary operators & operators – Provide “hook” for enabling arbitrary operations on tree nodes • Via Visitor pattern Constraints/ forces: – Treat operators & operands uniformly – No distinction between one & many Unary Node Leaf Nodes 51

  32. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Recursive Structure • Model a tree as a recursive Binary collection of nodes Nodes • Nodes are represented in an inheritance hierarchy that captures the particular properties of each node Unary • e.g., precedence levels, different Node associativities, & different arities • Binary nodes recursively contain Leaf two other nodes; unary nodes Nodes recursively contain one other node 52

  33. Pattern & Framework Tutorial Douglas C. Schmidt Overview of Tree Structure & Creation Patterns Interpreter < < use > > Expression_Tree_ Expression_Tree Interpreter_Context Context Interpreter < < create > > Component_Node Symbol Composite_ Composite_ Leaf_Node Number Operator Unary_Operator Binary_Node Unary_Node < < create > > Composite_ Composite_ Composite_ Add Substract Negate Add_Node Substract_Node Negate_Node Composite_ Composite_ Multiply Divide < < create > > Multiply_Node Divide_Node Composite Builder 53

  34. Pattern & Framework Tutorial Douglas C. Schmidt Component_Node Abstract base class for composable expression tree node objects I nterface : virtual ~ Component_Node (void)= 0 virtual int item (void) const virtual Component_Node * left (void) const virtual Component_Node * right (void) const virtual void accept (Visitor &visitor) const Subclasses : Leaf_Node , Composite_Unary_Node , Composite_Binary_Node , etc. Commonality : base class interface is used by all nodes in an expression tree Variability : each subclass defines state & method implementations that are specific for the various types of nodes 54

  35. Pattern & Framework Tutorial Douglas C. Schmidt Component_Node Hierarchy Note the inherent recursion in this hierarchy  i.e., a Composite_Binary_Node is a Component_Node & a Composite_Binary_Node also has Component_Node s! 55

  36. Pattern & Framework Tutorial Douglas C. Schmidt Composite object structural I ntent treat individual objects & multiple, recursively-composed objects uniformly Applicability objects must be composed recursively, and no distinction between individual & composed elements, and objects in structure can be treated uniformly Structure e.g., Component_Node e.g., Composite_Unary_Node, Composite_Binary_Node, etc. e.g., Leaf_Node 56

  37. Pattern & Framework Tutorial Douglas C. Schmidt Composite object structural Consequences Known Uses + uniformity: treat components the same – ET+ + Vobjects regardless of complexity – InterViews Glyphs, + extensibility: new Component subclasses work Styles wherever old ones do – Unidraw Components, – overhead: might need prohibitive numbers of MacroCommands objects – Directory structures – Awkward designs: may need to treat leaves as on UNIX & Windows lobotomized composites – Naming Contexts in I mplementation CORBA – do Components know their parents? – MIME types in SOAP – uniform interface for both leaves & composites? – don’t allocate storage for children in Component base class – responsibility for deleting children 57

  38. Pattern & Framework Tutorial Douglas C. Schmidt Parsing Expressions & Creating Expression Tree Goals: Constraints/ forces: – Simplify & centralize the creation of all – Don’t recode existing nodes in the composite expression tree clients – Extensible for future types of – Add new expressions expression orderings without recompiling “in-order” expression = -5* (3+ 4) “pre-order” expression = * -5+ 34 “post-order” expression = 5-34+ * “level-order” expression = * -+ 534 Unary Node Leaf Nodes 58

  39. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Build Parse Tree Using Interpreter • Each make_tree() method in the appropriate state object uses an interpreter to create a parse tree that corresponds to the expression input • This parse tree is then traversed to build each node in the corresponding expression tree Interpreter_Context In_Order_ Uninitialized_ State make_tree() Interpreter 59

  40. Pattern & Framework Tutorial Douglas C. Schmidt Interpreter Parses expressions into parse tree & generate corresponding expression tree I nterface: Interpreter (void) virtual ~ Interpreter (void) Expression interpret (Interpreter_Context &context, uses _Tree const std::string &input) Interpreter_Context (void) creates ~ Interpreter_Context (void) Symbol (Symbol * left, int get (std::string variable) Symbol * right) void set (std::string variable, int value) virtual ~ Symbol (void) void print (void) virtual int precedence (void)= 0 void reset (void) virtual Component_Node * build (void)= 0 Commonality : Provides a common interface for parsing expression input & building expression trees Variability : The structure of the expression trees can vary depending on the format & contents of the expression input 60

  41. Pattern & Framework Tutorial Douglas C. Schmidt Interpreter class behavioral I ntent Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language Applicability – When the grammar is simple & relatively stable – Efficiency is not a critical concern Structure 61

  42. Pattern & Framework Tutorial Douglas C. Schmidt Interpreter class behavioral Consequences Known Uses + Simple grammars are easy to change & extend, e.g., • Text editors &Web all rules represented by distinct classes in an orderly browsers use manner Interpreter to lay + Adding another rule adds another class out documents & – Complex grammars are hard to implement & check spelling maintain, e.g., more interdependent rules yield more • For example, an interdependent classes equation in TeX is I mplementation represented as a • Express the language rules, one per class tree where internal nodes are • Alternations, repetitions, or sequences expressed as operators, e.g. nonterminal expresssions square root, & • Literal translations expressed as terminal expressions leaves are • Create interpret method to lead the context through variables the interpretation classes 62

  43. Pattern & Framework Tutorial Douglas C. Schmidt Builder object creational I ntent Separate the construction of a complex object from its representation so that the same construction process can create different representations Applicability – Need to isolate knowledge of the creation of a complex object from its parts – Need to allow different implementations/interfaces of an object's parts Structure 63

  44. Pattern & Framework Tutorial Douglas C. Schmidt Builder object creational Consequences Known Uses • ACE Service Configurator + Can vary a product's internal representation framework + Isolates code for construction & representation + Finer control over the construction process I mplementation • The Builder pattern is basically a Factory pattern with a mission • A Builder pattern implementation exposes itself as a factory, but goes beyond the factory implementation in that various implementations are wired together 64

  45. Pattern & Framework Tutorial Douglas C. Schmidt Summary of Tree Structure & Creation Patterns Interpreter < < use > > Expression_Tree_ Expression_Tree Interpreter_Context Context Interpreter < < create > > Component_Node Symbol Composite_ Composite_ Leaf_Node Number Operator Unary_Operator Binary_Node Unary_Node < < create > > Composite_ Composite_ Composite_ Add Substract Negate Add_Node Substract_Node Negate_Node Composite_ Composite_ Multiply Divide < < create > > Multiply_Node Divide_Node Composite Builder 65

  46. Pattern & Framework Tutorial Douglas C. Schmidt Overview of Tree Traversal Patterns Visitor Iterator < < accept > > Expression_Tree Component_Node Visitor < < create > > Expression_Tree_ Expression_Tree_ Evaluation_Visitor Print_Visitor Iterator Iterator_Impl Level_Order_Expression_ LQueue Tree_Iterator_Impl In_Order_Expression_ Bridge std::stack Tree_Iterator_Impl Post_Order_Expression_ Tree_Iterator_Impl Pre_Order_Expression_ Tree_Iterator_Impl 66

  47. Pattern & Framework Tutorial Douglas C. Schmidt Encapsulating Variability & Simplifying Memory Managment Goals – Hide many sources of variability in expression tree construction & use – Simplify C+ + memory management, i.e., minimize use of new/delete in application code Constraints/ forces: – Must account for the fact that STL algorithms & iterators have “value semantics” for (Expression_Tree::iterator iter = tree.begin (); iter != tree.end (); ++iter) (*iter).accept (print_visitor); – Must ensure that exceptions don’t cause memory leaks 67

  48. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Decouple Interface & Implementation(s) Expression_Tree • Create a public interface class ( Expression_Tree ) used by clients & a private implementation hierarchy (rooted at Component_Node ) that encapsulates variability • The public interface class can perform reference counting of implementation object(s) to automate memory management • An Abstract Factory can produce the right implementation (as seen later) 68

  49. Pattern & Framework Tutorial Douglas C. Schmidt Expression_Tree Interface for Composite pattern used to contain all nodes in expression tree I nterface: Expression_Tree (void) Expression_Tree (Component_Node * root) Expression_Tree (const Expression_Tree &t) void operator= (const Expression_Tree &t) ~ Expression_Tree (void) Component_Node * get_root (void) bool is_null (void) const const int item (void) const Expression_Tree left (void) Expression_Tree right (void) iterator begin (const std::string &traversal_order) iterator end (const std::string &traversal_order) const_iterator begin (const std::string &traversal_order) const const_iterator end (const std::string &traversal_order) const Commonality : Provides a common interface for expression tree operations Variability : The contents of the expression tree nodes can vary depending on the expression 69

  50. Pattern & Framework Tutorial Douglas C. Schmidt Bridge object structural I ntent Separate a (logical) abstraction interface from its (physical) implementation(s) Applicability – When interface & implementation should vary independently – Require a uniform interface to interchangeable class hierarchies Structure 70

  51. Pattern & Framework Tutorial Douglas C. Schmidt Bridge object structural Consequences + abstraction interface & implementation are independent + implementations can vary dynamically + Can be used transparently with STL algorithms & containers – one-size-fits-all Abstraction & Implementor interfaces I mplementation • sharing Implementors & reference counting • See reusable Refcounter template class (based on STL/boost shared_pointer ) • creating the right Implementor (often use factories) Known Uses • ET+ + Window/WindowPort • libg+ + Set/{ LinkedList, HashTable} • AWT Component/ComponentPeer 71

  52. Pattern & Framework Tutorial Douglas C. Schmidt Tree Printing & Evaluation Goals: Algo 1: Print all Algo 2: Evaluate – Create a framework for the values of the the “yield” of the performing algorithms that nodes in the tree nodes in the tree affect nodes in a tree Constraints/ forces: Binary Nodes – support multiple algorithms that can act on the expression tree – don’t tightly couple algorithms with expression tree structure Unary Node – e.g., don’t have “print” & “evaluate” methods in the node classes Leaf Nodes 72

  53. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Encapsulate Traversal I terator – encapsulates a traversal algorithm without exposing representation details to callers e.g., – “in-order iterator” = -5* (3+ 4) – “pre-order iterator” = * -5+ 34 Unary – “post-order iterator” = 5-34+ * Node – “level-order iterator” = * -+ 534 Leaf Expression_Tree_Iterator Expression_Tree_Iterator_Impl Nodes In_Order_Expression_Tree_Iterator_Impl Post_Order_Expression_Tree_Iterator_Impl Level_Order_Expression_Tree_Iterator_Impl Pre_Order_Expression_Tree_Iterator_Impl 73 Note use of the Bridge pattern to encapsulate variability

  54. Pattern & Framework Tutorial Douglas C. Schmidt Expression_Tree_Iterator Interface for Iterator pattern that traverses all nodes in tree expression I nterface: Expression_Tree_Iterator (const Expression_Tree_Iterator &) Expression_Tree_Iterator (Expression_Tree_Iterator_Impl * ) Expression_Tree operator * (void) const Expression_Tree operator * (void) const Expression_Tree_Iterator & operator+ + (void) Expression_Tree_Iterator operator+ + (int) bool operator= = (const Expression_Tree_Iterator &rhs) bool operator!= (const Expression_Tree_Iterator &rhs) Commonality : Provides a common interface for expression tree iterators that conforms to the standard STL iterator interface Variability : Can be configured with specific expression tree iterator algorithms via the Bridge & Abstract Factory patterns 74 See Expression_Tree_State.cpp for example usage

  55. Pattern & Framework Tutorial Douglas C. Schmidt Expression_Tree_Iterator_Impl Implementation of the Iterator pattern that is used to define the various iterations algorithms that can be performed to traverse the expression tree I nterface: Expression_Tree_Iterator_Impl (const Expression_Tree &tree) virtual ~ Expression_Tree_Iterator_Impl (void) virtual Expression_Tree operator * (void) = 0 virtual const Expression_Tree operator * (void) const = 0 virtual void operator+ + (void)= 0 virtual bool operator= = (const Expression_Tree_Iterator_Impl &rhs) const = 0 virtual bool operator!= (const Expression_Tree_Iterator_Impl &rhs) const = 0 virtual Expression_Tree_Iterator_Impl * clone (void)= 0 Commonality : Provides a common interface for implementing expression tree iterators that conforms to the standard STL iterator interface Variability : Can be subclasses to define various algorithms for accessing nodes in the expression trees in a particular traversal order 75

  56. Pattern & Framework Tutorial Douglas C. Schmidt Iterator object behavioral I ntent access elements of a aggregate (container) without exposing its representation Applicability – require multiple traversal algorithms over an aggregate – require a uniform traversal interface over different aggregates – when aggregate classes & traversal algorithm must vary independently Structure 76

  57. Pattern & Framework Tutorial Douglas C. Schmidt Comparing STL Iterators with GoF Iterators STL iterators have “value-semantics”, e.g.: for (Expression_Tree::iterator iter = tree.begin (”Level Order”); iter != tree.end (”Level Order”); ++iter) (*iter).accept (print_visitor); In contrast, “GoF iterators have “pointer semantics”, e.g.: iterator *iter; for (iter = tree.createIterator (”Level Order”); iter->done () == false; iter->advance ()) (iter->currentElement ())->accept (print_visitor); delete iter; Bridge pattern simplifies use of STL iterators in expression tree application 77

  58. Pattern & Framework Tutorial Douglas C. Schmidt Iterator object behavioral Consequences Known Uses • C+ + STL iterators + flexibility: aggregate & traversal are independent • JDK Enumeration, + multiple iterators & multiple traversal algorithms Iterator – additional communication overhead between • Unidraw Iterator iterator & aggregate – This is particularly problematic for iterators in concurrent or distributed systems I mplementation • internal versus external iterators • violating the object structure’s encapsulation • robust iterators • synchronization overhead in multi-threaded programs • batching in distributed & concurrent programs 78

  59. Pattern & Framework Tutorial Douglas C. Schmidt Visitor • Defines action(s) at each step of traversal & avoids wiring action(s) in nodes • Iterator calls nodes’s accept(Visitor) at each node, e.g.: void Leaf_Node::accept (Visitor &v) { v.visit (*this); } • accept() calls back on visitor using “static polymorphism” I nterface: virtual void visit (const Leaf_Node &node)= 0 virtual void visit (const Composite_Negate_Node &node)= 0 virtual void visit (const Composite_Add_Node &node)= 0 virtual void visit (const Composite_Subtract_Node &node)= 0 virtual void visit (const Composite_Divide_Node &node)= 0 virtual void visit (const Composite_Multiply_Node &node)= 0 Commonality : Provides a common accept () method for all expression tree nodes & common visit() method for all visitor subclasses Variability : Can be subclassed to define specific behaviors for the visitors & nodes 79

  60. Pattern & Framework Tutorial Douglas C. Schmidt Print_Visitor • Prints character code or value for each node class Print_Visitor : public Visitor { public: virtual void visit (const Leaf_Node &); virtual void visit (const Add_Node &); virtual void visit (const Divide_Node &); // etc. for all relevant Component_Node subclasses }; • Can be combined with any traversal algorithm, e.g.: Print_Visitor print_visitor; for (Expression_Tree::iterator iter = tree.begin (”post-order”); iter != tree.end (”post-order”); ++iter) (*iter).accept (print_visitor); // calls visit (*this); 80 See Expression_Tree_State.cpp for example usage

  61. Pattern & Framework Tutorial Douglas C. Schmidt Print_Visitor Interaction Diagram • The iterator controls the order in which accept() is called on each node in the composition • accept() then “visits” the node to perform the desired print action Leaf_Node (5) Composite_Negate_Node print_visitor accept(print_visitor) cout<< node.item (); accept(print_visitor) cout<< ‘-’ 81

  62. Pattern & Framework Tutorial Douglas C. Schmidt Evaluation_Visitor • This class serves as a visitor for class Evaluation_Visitor : evaluating nodes in an expression public Visitor { /* ... */ }; tree that is being traversed using a post-order iterator – e.g., 5-34+ * • It uses a stack to keep track of the post- order expression tree value that has been processed thus far during the iteration traversal, e.g.: 1. S = [5] push(node.item()) 2. S = [-5] push(-pop()) Unary 3. S = [-5, 3] push(node.item()) Node 4. S = [-5, 3, 4] push(node.item()) 5. S = [-5, 7] push(pop()+pop()) Leaf 6. S = [-35] push(pop()*pop()) Nodes 82

  63. Pattern & Framework Tutorial Douglas C. Schmidt Evaluation_Visitor Interaction Diagram • The iterator controls the order in which accept() is called on each node in the composition • accept() then “visits” the node to perform the desired evaluation action Leaf_Node (5) Composite_Negate_Node eval_visitor accept(eval_visitor) stack_.push(node.item ()); accept(eval_visitor) stack_.push(-stack_.pop()); 83

  64. Pattern & Framework Tutorial Douglas C. Schmidt Visitor object behavioral I ntent Centralize operations on an object structure so that they can vary independently but still behave polymorphically Applicability – when classes define many unrelated operations – class relationships of objects in the structure rarely change, but the operations on them change often – algorithms keep state that’s updated during traversal Structure Note “static polymorphism” based on method overloading by type 84

  65. Pattern & Framework Tutorial Douglas C. Schmidt Visitor object behavioral Consequences + flexibility: visitor algorithm(s) & object structure are independent + localized functionality in the visitor subclass instance – circular dependency between Visitor & Element interfaces – Visitor brittle to new ConcreteElement classes I mplementation • double dispatch • general interface to elements of object structure Known Uses • ProgramNodeEnumerator in Smalltalk-80 compiler • IRIS Inventor scene rendering • TAO IDL compiler to handle different backends 85

  66. Pattern & Framework Tutorial Douglas C. Schmidt Summary of Tree Traversal Patterns Visitor Iterator < < accept > > Expression_Tree Component_Node Visitor < < create > > Expression_Tree_ Expression_Tree_ Evaluation_Visitor Print_Visitor Iterator Iterator_Impl Level_Order_Expression_ LQueue Tree_Iterator_Impl In_Order_Expression_ Bridge std::stack Tree_Iterator_Impl Post_Order_Expression_ Tree_Iterator_Impl Pre_Order_Expression_ Tree_Iterator_Impl 86

  67. Pattern & Framework Tutorial Douglas C. Schmidt Overview of Command & Factory Patterns AbstractFactory Expression_Tree_ Expression_Tree_ Expression_Tree_Command_ Event_Handler Command_Factory Factory_Impl Concrete_Expression_Tree_ Expression_Tree_ < < create > > Command_Factory_Impl Context Expression_Tree_ Expression_Tree_ * Command Command_Impl 1 Macro_Command Print_Command Set_Command Quit_Command Null_Command Format_Command Expr_Command Eval_Command Command 87

  68. Pattern & Framework Tutorial Douglas C. Schmidt Consolidating User Operations Goals: % tree-traversal -v – support execution of format [in-order] user operations expr [expression] – support macro print [in-order|pre-order|post-order|level-order] commands eval [post-order] – support undo/redo quit > format in-order Constraints/ forces: > expr 1+ 2* 3/2 – scattered operation > print in-order implementations 1+ 2* 3/2 – Consistent memory > print pre-order management + 1/* 232 > eval post-order 4 > quit 88

  69. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Encapsulate Each Request w/Command A Command encapsulates Command may  implement the operations  an operation ( execute() ) itself, or  an inverse operation ( unexecute() )  delegate them to other  a operation for testing reversibility object(s) ( boolean reversible() )  state for (un)doing the operation Expression_Tree_Command Expression_Tree_Command_Impl Format_Command Print_Command Eval_Command Quit_Command Expr_Command Macro_Command Note use of Bridge pattern to encapsulate variability & simplify memory management 89

  70. Pattern & Framework Tutorial Douglas C. Schmidt Expression_Tree_Command Interface for Command pattern used to define a command that performs an operation on the expression tree when executed I nterface: Expression_Tree_Command (Expression_Tree_Command_Impl * = 0) Expression_Tree_Command (const Expression_Tree_Command &) Expression_Tree_Command & operator= (const Expression_Tree_Command &) ~ Expression_Tree_Command (void) bool execute (void) boolunexecute (void) Commonality : Provides a common interface for expression tree commands Variability : The implementations of the expression tree commands can vary depending on the operations requested by user input 90

  71. Pattern & Framework Tutorial Douglas C. Schmidt List of Commands = Execution History unexecute() unexecute() unexecute() execute() Undo: Redo: cmd cmd cmd cmd past future future past 91

  72. Pattern & Framework Tutorial Douglas C. Schmidt Command object behavioral I ntent Encapsulate the request for a service Applicability – to parameterize objects with an action to perform – to specify, queue, & execute requests at different times – for multilevel undo/redo Structure 92

  73. Pattern & Framework Tutorial Douglas C. Schmidt Command object behavioral Consequences Known Uses • InterViews Actions + abstracts executor of a service • MacApp, Unidraw Commands + supports arbitrary-level undo-redo • JDK’s UndoableEdit, + composition yields macro-commands AccessibleAction – might result in lots of trivial command • Emacs subclasses • Microsoft Office tools – excessive memory may be needed to support undo/redo operations I mplementation • copying a command before putting it on a history list • handling hysteresis • supporting transactions 93

  74. Pattern & Framework Tutorial Douglas C. Schmidt Consolidating Creation of Variabilities Goals: Constraints/ forces: – Simplify & centralize the creation of all – Don’t recode variabilities in the expression tree existing clients application to ensure semantic compatibility – Add new variabilities – Be extensible for future variabilities without recompiling Expression_Tree_Command Expression_Tree_Command_Impl Format_Command Print_Command Eval_Command Quit_Command Expr_Command Macro_Command Expression_Tree_Iterator Expression_Tree_Iterator_Impl In_Order_Expression_Tree_Iterator_Impl Post_Order_Expression_Tree_Iterator_Impl Level_Order_Expression_Tree_Iterator_Impl Pre_Order_Expression_Tree_Iterator_Impl 94

  75. Pattern & Framework Tutorial Douglas C. Schmidt Solution: Abstract Object Creation Instead of Expression_Tree_Command command = new Print_Command (); Use Expression_Tree_Command command = command_factory.make_command (“print”); where command_factory is an instance of Expression_Tree_Command_Factory or anything else that makes sense wrt our goals Expression_Tree_Command_Factory Expression_Tree_Command_Factory_Impl Concrete_Expression_Tree_ Command_Factory_Impl 95

  76. Pattern & Framework Tutorial Douglas C. Schmidt Expression_Tree_Command_Factory Interface for Abstract Factory pattern used to create appropriate command based on string supplied by caller Expression_Tree_Command_Factory I nterface: (Expression_Tree_Context &tree_context) Expression_Tree_Command_Factory (const Expression_Tree_Command_Factory &f) void operator= (const Expression_Tree_Command_Factory &f) ~ Expression_Tree_Command_Factory (void) Expression_Tree_Command make_command (const std::string &s) Expression_Tree_Command make_format_command (const std::string &) Expression_Tree_Command make_expr_command (const std::string &) Expression_Tree_Command make_print_command (const std::string &) Expression_Tree_Command make_eval_command (const std::string &) Expression_Tree_Command make_quit_command (const std::string &) Expression_Tree_Command make_macro_command (const std::string &) Commonality : Provides a common interface to create commands Variability : The implementations of the expression tree command factory methods can vary depending on the requested commands 96

  77. Pattern & Framework Tutorial Douglas C. Schmidt Factory Structure Expression_Tree_Command_ Factory Expression_Tree_Command Expression_Tree_Command_ Factory_Impl Expression_Tree_Command_Impl Concrete_Expression_Tree_ Command_Factory_Impl Format_Command make_format_command() Expr_Command make_expr_command() make_print_command() Print_Command make_eval_command() Eval_Command make_macro_command() Macro_Command make_quit_command() Quit_Command Note use of Bridge pattern to encapsulate variability & simplify memory management 97

  78. Pattern & Framework Tutorial Douglas C. Schmidt Factory Method class creational I ntent Provide an interface for creating an object, but leave choice of object’s concrete type to a subclass Applicability when a class cannot anticipate the objects it must create or a class wants its subclasses to specify the objects it creates Structure 98

  79. Pattern & Framework Tutorial Douglas C. Schmidt Factory Method class creational Consequences Known Uses + By avoiding to specify the class name of the • InterViews Kits concrete class &the details of its creation the • ET+ + client code has become more flexible WindowSystem + The client is only dependent on the interface • AWT Toolkit - Construction of objects requires one additional • The ACE ORB (TAO) class in some cases • BREW I mplementation • UNIX open() syscall • There are two choices here • The creator class is abstract & does not implement creation methods (then it must be subclassed) • The creator class is concrete & provides a default implementation (then it can be subclassed) • Should a factory method be able to create different variants? If so the method must be equipped with a parameter 99

  80. Pattern & Framework Tutorial Douglas C. Schmidt Abstract Factory object creational I ntent create families of related objects without specifying subclass names Applicability when clients cannot anticipate groups of classes to instantiate Structure See Uninitialized_State_Factory & Expression_Tree_Event_Handler for Factory pattern variants 100

Recommend


More recommend