149
Object-Oriented Patterns & Frameworks Dr. Douglas C. Schmidt [email protected] www.dre.vanderbilt.edu/~schmidt Professor of EECS Vanderbilt University Nashville, Tennessee

Object-Oriented Patterns & Frameworks

  • Upload
    tirzah

  • View
    47

  • Download
    0

Embed Size (px)

DESCRIPTION

Object-Oriented Patterns & Frameworks. Dr. Douglas C. Schmidt [email protected] www.dre.vanderbilt.edu /~ schmidt. Professor of EECS Vanderbilt University Nashville, Tennessee. Client. Proxy. Service. AbstractService. service. service. service. 1. 1. Goals of this Presentation. - PowerPoint PPT Presentation

Citation preview

An Introduction to Design Patterns

Object-Oriented Patterns & FrameworksDr. Douglas C. Schmidt [email protected]/~schmidtProfessor of EECS Vanderbilt University Nashville, Tennessee

Pattern & Framework TutorialDouglas C. Schmidt#1Goals of this PresentationShow by example how patterns & frameworks can help toCodify good OO software design & implementation practicesdistill & generalize experienceaid to novices & experts alikeGive design structures explicit namescommon vocabularyreduced complexitygreater expressivityCapture & preserve design & implementation knowledgearticulate key decisions succinctlyimprove documentationFacilitate restructuring/refactoringpatterns & frameworks are interrelatedenhance flexibility, reuse, & productivity11ProxyserviceServiceserviceAbstractServiceserviceClientclass Reactor {public: /// Singleton access point. static Reactor *instance (void);

/// Run event loop. void run_event_loop (void);

/// End event loop. void end_event_loop (void);

/// Register @a event_handler /// for input events. void register_input_handler (Event_Handler *eh);

/// Remove @a event_handler /// for input events. void remove_input_handler (Event_Handler *eh);Pattern & Framework TutorialDouglas C. Schmidt#2

LeafNodesBinaryNodesUnaryNodeTutorial OverviewPart I: Motivation & ConceptsThe issueWhat patterns & frameworks areWhat theyre good forHow we develop/categorize themPart II: Case StudyUse patterns & frameworks to build an expression tree applicationDemonstrate usage & benefitsPart III: Wrap-UpLife beyond the GoF book, observations, caveats, concluding remarks, & additional references

Pattern & Framework TutorialDouglas C. Schmidt#3

Part I: Motivation & ConceptsOOD methods emphasize design notationsFine for specification & documentation

Pattern & Framework TutorialDouglas C. Schmidt#4Part I: Motivation & ConceptsOOD methods emphasize design notationsFine for specification & documentationBut OOD is more than just drawing diagramsGood draftsmen are not necessarily good architects!

Pattern & Framework TutorialDouglas C. Schmidt#5Part I: Motivation & ConceptsOOD methods emphasize design notationsFine for specification & documentationBut OOD is more than just drawing diagramsGood draftsmen are not necessarily good architects! Good OO designers rely on lots of experienceAt least as important as syntaxMost powerful reuse combines design & code reusePatterns: Match problem to design experience

Frameworks: Reify patterns within a domain contexts->getData()ObserverupdateConcreteObserverupdatedoSomethingstate = X;notify(); SubjectattachdetachnotifysetDatagetDatastateobserverListfor all observersin observerList do update(); *

Pattern & Framework TutorialDouglas C. Schmidt#6Recurring Design StructuresWell-designed OO systems exhibit recurring structures that promoteAbstractionFlexibilityModularityElegance

Therein lies valuable design knowledgeProblem: capturing, communicating, applying, & preserving this knowledge without undue time, effort, & risk

Pattern & Framework TutorialDouglas C. Schmidt#7A PatternAbstracts & names a recurring design structureComprises class and/or objectDependenciesStructuresInteractionsConventionsSpecifies the design structure explicitlyIs distilled from actual design experience

Presents solution(s) to common (software) problem(s) arising within a contextThe Proxy Pattern11ProxyserviceServiceserviceAbstractServiceserviceClientPattern & Framework TutorialDouglas C. Schmidt#8Four Basic Parts of a PatternNameProblem (including forces & applicability)Solution (both visual & textual descriptions)Consequences & trade-offs of applying the patternKey characteristics of patterns include:Language- & implementation-independentMicro-architecture i.e., society of objectsAdjunct to existing methodologies e.g., RUP, Fusion, SCRUM, etc.The Proxy Pattern11ProxyserviceServiceserviceAbstractServiceserviceClientPattern & Framework TutorialDouglas C. Schmidt#9Example: Observer

Pattern & Framework TutorialDouglas C. Schmidt#10Intentdefine a one-to-many dependency between objects so that when one object changes state, all dependents are notified & updated

Applicabilityan abstraction has two aspects, one dependent on the othera change to one object requires changing untold othersan object should notify unknown other objectsStructure

Observer object behavioralPattern & Framework TutorialDouglas C. Schmidt#11Modified UML/OMT Notation

Pattern & Framework TutorialDouglas C. Schmidt#12

class ProxyPushConsumer : public // virtual void push (const CORBA::Any &event) { for (std::vector::iterator i (consumers.begin ()); i != consumers.end (); i++) (*i).push (event); }CORBA Notification Service example using C++ Standard Template Library (STL) iterators (which is an example of the Iterator pattern from GoF)class MyPushConsumer : public // . virtual void push (const CORBA::Any &event) { /* consume the event. */ }Observer object behavioralPattern & Framework TutorialDouglas C. Schmidt#13Consequencesmodularity: subject & observers may vary independentlyextensibility: can define & add any number of observerscustomizability: different observers offer different views of subjectunexpected updates: observers dont know about each otherupdate overhead: might need hints or filteringImplementationsubject-observer mappingdangling referencesupdate protocols: the push & pull modelsregistering modifications of interest explicitlyObserver object behavioralKnown UsesSmalltalk Model-View-Controller (MVC)InterViews (Subjects & Views, Observer/Observable)Andrew (Data Objects & Views)Smart phone event frameworks (e.g., Symbian, Android, iPhone)Pub/sub middleware (e.g., CORBA Notification Service, Java Message Service, DDS)Mailing listsPattern & Framework TutorialDouglas C. Schmidt#14Design Space for GoF Patterns

Scope: domain over which a pattern appliesPurpose: reflects what a pattern doesPattern & Framework TutorialDouglas C. Schmidt#15GoF Pattern Template (1st half)Intentshort description of the pattern & its purposeAlso Known AsAny aliases this pattern is known byMotivationmotivating scenario demonstrating patterns useApplicabilitycircumstances in which pattern appliesStructuregraphical representation of pattern using modified UML notationParticipantsparticipating classes and/or objects & their responsibilitiesPattern & Framework TutorialDouglas C. Schmidt#16

GoF Pattern Template (2nd half)...Collaborationshow participants cooperate to carry out their responsibilitiesConsequencesthe results of application, benefits, liabilitiesImplementationpitfalls, hints, techniques, plus language-dependent issuesSample Codesample implementations in C++, Java, C#, Python, Smalltalk, C, etc.Known Usesexamples drawn from existing systemsRelated Patternsdiscussion of other patterns that relate to this onePattern & Framework TutorialDouglas C. Schmidt#17Benefits & Limitations of PatternsBenefitsDesign reuseUniform design vocabularyEnhance understanding, restructuring, & team communicationBasis for automationTranscends language-centric biases/myopiaAbstracts away from many unimportant details

LimitationsRequire significant tedious & error-prone human effort to handcraft pattern implementations design reuseCan be deceptively simple uniform design vocabularyMay limit design optionsLeaves important (implementation) details unresolved

Addressing the limitations of patterns requires more than just design reusePattern & Framework TutorialDouglas C. Schmidt#18Overview of FrameworksApplication-specific functionality Frameworks exhibit inversion of control at runtime via callbacksNetworking DatabaseGUI Frameworks provide integrated domain-specific structures & functionalityMission ComputingE-commerceScientificVisualizationFrameworks are semi-complete applicationsPattern & Framework TutorialDouglas C. Schmidt#19

Legacy embedded systems have historically been:StovepipedProprietary Brittle & non-adaptiveExpensiveVulnerable

Consequence: Small HW/SW changes have big (negative) impact on system QoS & maintenanceMotivation for FrameworksApplicationSoftwareApplicationSoftwareApplicationSoftwareApplicationSoftware

Proprietary & Stovepiped Application & Infrastructure SoftwareStandard/COTS Hardware & Networks

Pattern & Framework TutorialDouglas C. Schmidt#20

ProductVariant 1ProductVariant 4ProductVariant 2ProductVariant 3Frameworks factors out many reusable general-purpose & domain-specific services from traditional DRE application responsibility Essential for product-line architectures (PLAs)Product-lines & frameworks offer many configuration opportunitiese.g., component distribution/deployment, OS, protocols, algorithms, etc.Motivation for Frameworks

Product-Line Architecture-based Application & Framework SoftwareStandard/COTS Hardware & NetworksPattern & Framework TutorialDouglas C. Schmidt#21Categories of OO FrameworksWhite-box frameworks are reused by subclassing, which usually requires understanding the implementation of the framework to some degreeBlack-box framework is reused by parameterizing & assembling framework objects, thereby hiding their implementation from usersEach category of OO framework uses different sets of patterns, e.g.:

Many frameworks fall in between white-box & black-box categories

White-box frameworks rely heavily on inheritance-based patterns, such as Template Method & StateBlack-box frameworks reply heavily on object composition patterns, such as Strategy & DecoratorPattern & Framework TutorialDouglas C. Schmidt#22

Framework characteristics are captured via Scope, Commonalities, & Variabilities (SCV) analysisThis process can be applied to identify commonalities & variabilities in a domain to guide development of a frameworkApplying SCV to Android smartphonesScope defines the domain & context of the frameworkComponent architecture, object-oriented application frameworks, & associated components, e.g., GPS, Network, & Display Reusable Architecture FrameworkReusable Application ComponentsCommonality & Variability Analysis in FrameworksPattern & Framework TutorialDouglas C. Schmidt#23

Linux KernelDevice Driver FrameworkNetworking I/O FrameworkApplication FrameworksActivity ManagerWindowManagerLocationManagerApplicationsPhoneEmailBrowserPattern & Framework TutorialDouglas C. Schmidt#24Applying SCV to an Android FrameworkCommonalities describe the attributes that are common across all members of the frameworkCommon object-oriented frameworks & set of component typese.g., Activities, Services, Content Providers, & Display componentsCommon middleware infrastructuree.g., Intents framework, Binder, etc.

Pattern & Framework TutorialDouglas C. Schmidt#25Variabilities describe the attributes unique to the different members of the frameworkProduct-dependent component implementations, e.g., Motorola, HTC, SamsugProduct-dependent component connectionsProduct-dependent component assemblies (e.g., CDMA vs. GSM in different countries)Different hardware, OS, & network/bus configurations Applying SCV to an Android Framework

Pattern & Framework TutorialDouglas C. Schmidt#26Arvind, what is a variant specific component. Also I think there might be a need for a hyphen there. Also what is the purpose of the bullet individual component impl?

Arvind: Andy, it is to say that different variants can have different implementations. For example, One can have a GPS implementation while another can have a INS systems.

Timers can run at 40 Hz & others can run at 20 Hz

OK - andyComparing Reuse TechniquesClass Library (& STL) ArchitectureADTsStringsLocksIPCMathLOCAL INVOCATIONSAPPLICATION-SPECIFICFUNCTIONALITYEVENTLOOPGLUECODEFilesGUIA class is an implementation unit in an OO programming language, i.e., a reusable type that often implements patternsClasses in class libraries are typically passiveFramework Architecture

ADTsLocksStringsFilesINVOKESA framework is an integrated set of classes that collaborate to form a reusable architecture for a family of applicationsFrameworks implement pattern languagesReactor GUIDATABASE NETWORKINGAPPLICATION-SPECIFIC FUNCTIONALITYCALLBACKS Middleware BusComponent & Service-Oriented ArchitectureA component is an encapsulation unit with one or more interfaces that provide clients with access to its servicesComponents can be deployed & configured via assembliesNamingLockingLoggingEventsPattern & Framework TutorialDouglas C. Schmidt#27Taxonomy of Reuse TechniquesClass LibrariesFrameworksMacro-levelMeso-levelMicro-levelBorrow callers threadInversion of controlBorrow callers threadDomain-specific or Domain-independentDomain-specificDomain-independentStand-alone composition entitiesSemi-complete applicationsStand-alone language entitiesComponentsPattern & Framework TutorialDouglas C. Schmidt#28Benefits of FrameworksCommunicationServicesOS-AccessLayerBrokerComponentRepositoryComponentConfiguratorProxyProxyBrokerAdminControllersAdminViewsAdminClientPickingControllersPickingViewsPickingClientBrokerLoggingHandlerThreadPool*ReactorBrokerScheduler/ActivationListServiceRequestServiceRequestServiceRequestWarehouseRepHalfXDistributionInfrastructureConcurrencyInfrastructureThin UI ClientsDesign reusee.g., by guiding application developers through the steps necessary to ensure successful creation & deployment of softwarePattern & Framework TutorialDouglas C. Schmidt#29package org.apache.tomcat.session;

import org.apache.tomcat.core.*;import org.apache.tomcat.util.StringManager;import java.io.*;import java.net.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;

/** * Core implementation of a server session * * @author James Duncan Davidson [[email protected]] * @author James Todd [[email protected]] */

public class ServerSession {

private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private Hashtable appSessions = new Hashtable(); private String id; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime;private int inactiveInterval = -1; ServerSession(String id) { this.id = id; }

public String getId() { return id; }

public long getCreationTime() { return creationTime; }

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); }Benefits of FrameworksDesign reusee.g., by guiding application developers through the steps necessary to ensure successful creation & deployment of softwareImplementation reusee.g., by amortizing software lifecycle costs & leveraging previous development & optimization effortsPattern & Framework TutorialDouglas C. Schmidt#30Design reusee.g., by guiding application developers through the steps necessary to ensure successful creation & deployment of softwareImplementation reusee.g., by amortizing software lifecycle costs & leveraging previous development & optimization effortsValidation reusee.g., by amortizing the efforts of validating application- & platform-independent portions of software, thereby enhancing software reliability & scalability

Benefits of FrameworksPattern & Framework TutorialDouglas C. Schmidt#31Frameworks are powerful, but can be hard to use effectively (& even harder to create) for many application developersCommonality & variability analysis requires significant domain knowledge & OO design/implementation expertiseSignificant time required to evaluate applicability & quality of a framework for a particular domainDebugging is tricky due to inversion of controlV&V is tricky due to late bindingMay incur performance degradations due to extra (unnecessary) levels of indirectionwww.cs.wustl.edu/ ~schmidt/PDF/Queue-04.pdfLimitations of FrameworksMany frameworks limitations can be addressed with knowledge of patterns!Pattern & Framework TutorialDouglas C. Schmidt#32Using Frameworks EffectivelyObservationsSince frameworks are powerfulbut but hard to develop & use effectively by application developersits often better to use & customize COTS frameworks than to develop in-house frameworksClasses/components/services are easier for application developers to use, but arent as powerful or flexible as frameworks

Successful projects are therefore often organized using the funnel modelPattern & Framework TutorialDouglas C. Schmidt#33Stages of Pattern & Framework Awareness

Pattern & Framework TutorialDouglas C. Schmidt#34Part II: Case Study: Expression Tree ApplicationGoalsDevelop an object-oriented expression tree evaluator program using patterns & frameworksDemonstrate commonality/variability analysis in the context of a concrete application exampleIllustrate how OO frameworks can be combined with the generic programming features of C++ & STLCompare/contrast OO & non-OO approaches

LeafNodesBinaryNodesUnaryNodePattern & Framework TutorialDouglas C. Schmidt#35

LeafNodesBinaryNodesUnaryNodeExpression trees consist of nodes containing operators & operands Operators have different precedence levels, different associativities, & different arities, e.g.: Multiplication takes precedence over additionThe multiplication operator has two arguments, whereas unary minus operator has only one Operands can be integers, doubles, variables, etc.We'll just handle integers in this applicationApplication can be extended easilyOverview of Expression Tree ApplicationPattern & Framework TutorialDouglas C. Schmidt#36See www.dre.vanderbilt.edu/~schmidt/qualcomm/tree-traversal.zip

LeafNodesBinaryNodesUnaryNodeTrees may be evaluated via different traversal orderse.g., in-order, post-order, pre-order, level-orderThe evaluation step may perform various operations, e.g.:Print the contents of the expression treeReturn the value" of the expression treeGenerate codePerform semantic analysis & optimizationetc.Overview of Expression Tree ApplicationPattern & Framework TutorialDouglas C. Schmidt#37Using the Expression Tree Application% tree-traversal> 1+4*3/27> (8/4) * 3 + 17^D

% tree-traversal -vformat [in-order]expr [expression]print [in-order|pre-order|post-order|level-order]eval [post-order]quit> format in-order> expr 1+4*3/2> eval post-order7> quit

By default, the expression tree application can run in succinct mode, e.g.:You can also run the expression tree application in verbose mode, e.g.:Pattern & Framework TutorialDouglas C. Schmidt#38How Not to Design an Expression Tree ApplicationA 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; Pattern & Framework TutorialDouglas C. Schmidt#39Heres the memory layout & class diagram for a struct Tree_Node:

How Not to Design an Expression Tree ApplicationPattern & Framework TutorialDouglas C. Schmidt#40A 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 ");} How Not to Design an Expression Tree ApplicationPattern & Framework TutorialDouglas C. Schmidt#41Limitations with the Algorithmic ApproachLittle or no use of encapsulation: implementation details available to clientsIncomplete modeling of the application domain, which results inTight coupling between nodes/edges in union representationComplexity being in algorithms rather than the data structures e.g., switch statements are used to select between various types of nodes in the expression treesData structures are passive functions that do their work explicitlyThe program organization makes it hard to extende.g., small changes will ripple through the entire design & implementationEasy to make mistakes switching on type tags Wastes space by making worst-case assumptions wrt structs & unionsPattern & Framework TutorialDouglas C. Schmidt#42An OO Alternative Using Patterns & FrameworksStart with OO modeling of the expression tree application domain

Conduct commonality/variability analysis (CVA) to determine stable interfaces & points of variabilityApply patterns to guide design/implementation of frameworkIntegrate w/C++ STL algorithms/containers when appropriate

LeafNodesBinaryNodesUnaryNodeModel a tree as a collection of nodesNodes are represented in an inheritance hierarchy that captures the particular properties of each nodee.g., precedence levels, different associativities, & different aritiesApplication-dependent steps Application-independent steps Pattern & Framework TutorialDouglas C. Schmidt#43Design Problems & Pattern-Oriented Solutions

LeafNodesBinaryNodesUnaryNodeDesign ProblemPattern(s)Expression tree structure CompositeEncapsulating variability & simplifying memory management BridgeTree printing & evaluation Iterator & VisitorConsolidating user operations CommandEnsuring correct protocol for commands StateConsolidating creation of Variabilities Abstract Factory & Factory MethodParsing expressions & creating expression tree Interpreter & BuilderPattern & Framework TutorialDouglas C. Schmidt#44Design Problems & Pattern-Oriented SolutionsNone of these patterns are restricted to expression tree applications

LeafNodesBinaryNodesUnaryNodeDesign ProblemPattern(s)Driving the application event flow ReactorSupporting multiple operation modesTemplate Method & StrategyCentralizing global objects effectively SingletonImplementing STL iterator semantics PrototypeEliminating loops via the STL std::for_each() algorithmAdapterProvide no-op commandsNull ObjectPattern & Framework TutorialDouglas C. Schmidt#45Managing Global Objects EffectivelyGoals:Centralize access to objects that should be visible globally, e.g.:command-line options that parameterize the behavior of the programThe object (Reactor) that drives the main event loopConstraints/forces:Only need one instance of the command-line options & ReactorGlobal variables are problematic in C++% tree-traversal -vformat [in-order]expr [expression]print [in-order|pre-order|post-order|level-order]eval [post-order]quit> format in-order> expr 1+4*3/2> eval post-order7> quit

% tree-traversal> 1+4*3/27

Verbose modeSuccinct modePattern & Framework TutorialDouglas C. Schmidt#46Solution: Centralize Access to Global InstancesRather 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); // ... Pattern & Framework TutorialDouglas C. Schmidt#47Singleton object creationalIntentensure a class only ever has one instance & provide a global point of access Applicabilitywhen there must be exactly one instance of a class & it must be accessible from a well-known access pointwhen the sole instance should be extensible by subclassing & clients should be able to use an extended instance without modifying their codeStructure

If (uniqueInstance == 0) uniqueInstance = new Singleton;return uniqueInstance;Pattern & Framework TutorialDouglas C. Schmidt#48Consequencesreduces namespace pollutionmakes it easy to change your mind & allow more than one instanceallow extension by subclassingsame drawbacks of a global if misusedimplementation may be less efficient than a global concurrency/cache pitfalls & communication overheadImplementationstatic instance operationregistering the singleton instancedeleting singletons Known UsesUnidraw's Unidraw objectSmalltalk-80 ChangeSet, the set of changes to codeInterViews Session objectSee AlsoDouble-Checked Locking Optimization pattern from POSA2To Kill a Singleton www.research.ibm.com/ designpatterns/pubs/ ph-jun96.txtSingleton object creationalPattern & Framework TutorialDouglas C. Schmidt#49CompositeCompositeBuilderInterpreterExpression_Tree_ContextExpression_TreeInterpreterInterpreter_ContextSymbolOperatorUnary_OperatorNumberSubstractAddNegateMultiplyDivideComponent_NodeComposite_Binary_NodeComposite_Unary_NodeLeaf_NodeComposite_Substract_NodeComposite_Add_NodeComposite_Negate_NodeComposite_Multiply_NodeComposite_Divide_NodeOverview of Tree Structure & Creation Patterns>>>>Patterns (& pattern combos) help focus on forests rather than (just) treesPurpose: Parse the input & create the key internal data structure for the expression treePattern & Framework TutorialDouglas C. Schmidt#50

LeafNodesUnaryNodeExpression Tree StructureGoals:Support physical structure of expression tree e.g., binary/unary operators & operatorsProvide hook for enabling arbitrary operations on tree nodes Via Visitor pattern (described later)

Constraints/forces:Treat operators & operands uniformlyNo distinction between one vs. many to avoid/minimize special casesPattern & Framework TutorialDouglas C. Schmidt#51Solution: Recursive Structure

LeafNodesBinaryNodesUnaryNodeModel a tree as a recursive collection of nodesNodes are represented in an inheritance hierarchy that captures the particular properties of each nodee.g., precedence levels, different associativities, & different aritiesBinary nodes recursively contain two other child nodes; unary nodes recursively contain one other child nodePattern & Framework TutorialDouglas C. Schmidt#52Component_NodeAbstract base class for composable expression tree node objectsInterface:Subclasses: Leaf_Node, Composite_Unary_Node, Composite_Binary_Node, etc.virtual~Component_Node (void)=0virtual intitem (void) const virtual Component_Node *left (void) const virtual Component_Node *right (void) const virtual voidaccept (Visitor &visitor) const Commonality: base class interface is used by all nodes in an expression treeVariability: each subclass defines state & method implementations that are specific for the various types of nodesPattern & Framework TutorialDouglas C. Schmidt#53Component_Node HierarchyNote the inherent recursion in this hierarchyi.e., a Composite_Binary_Node is a Component_Node & a Composite_Binary_Node also has Component_Nodes!

Pattern & Framework TutorialDouglas C. Schmidt#54Composite object structuralIntenttreat individual objects & multiple, recursively-composed objects uniformlyApplicabilityobjects must be composed recursively,and no distinction between individual & composed elements,and objects in structure can be treated uniformlyStructure

e.g., Leaf_Nodee.g., Component_Nodee.g., Composite_Unary_Node, Composite_Binary_Node, etc.Pattern & Framework TutorialDouglas C. Schmidt#55Consequencesuniformity: treat components the same regardless of complexityextensibility: new Component subclasses work wherever old ones dooverhead: might need prohibitive numbers of objects Awkward designs: may need to treat leaves as lobotomized composites in some casesImplementationdo Components know their parents?uniform interface for both leaves & composites?dont allocate storage for children in Component base classresponsibility for deleting childrenKnown UsesET++ VobjectsInterViews Glyphs, StylesUnidraw Components, MacroCommandsDirectory structures on UNIX & WindowsNaming Contexts in CORBAMIME types in SOAPComposite object structuralPattern & Framework TutorialDouglas C. Schmidt#56

Parsing Expressions & Creating Expression TreeGoals:Simplify & centralize the creation of all nodes in the composite expression treeExtensible for future types of expression orderings & optimizationsConstraints/forces:Dont recode existing clients when changes occurAdd new expressions without recompiling existing codein-order expression = -5*(3+4)pre-order expression = *-5+34post-order expression = 5-34+*level-order expression = *-+534

Pattern & Framework TutorialDouglas C. Schmidt#57

Solution: Build Parse Tree Using InterpreterUse an interpreter to create a parse tree corresponding to input expression This parse tree is then traversed to build the appropriate type of nodes in the corresponding expression treeWe create the entire parse tree to enable future optimizationsInterpreterInterpreter_ContextIn_Order_ Uninitialized_Statemake_tree()This class uses the State & Factory Method patterns (described later)Pattern & Framework TutorialDouglas C. Schmidt#58InterpreterParses expressions into parse tree & generate corresponding expression treeInterface:Commonality: Provides a common interface for parsing expression input & building parse trees & expression treesVariability: The structure of the parse trees & expression trees can vary depending on the format & contents of the expression input Interpreter (void)virtual ~Interpreter (void)Expression _Tree interpret (Interpreter_Context &context, const std::string &input)Interpreter_Context (void)~Interpreter_Context (void)intget (std::string variable)voidset (std::string variable, int value)voidprint (void)voidreset (void)Symbol (Symbol *left, Symbol *right)virtual~Symbol (void)virtual intprecedence (void)=0virtual Component_Node *build (void)=0usescreatesPattern & Framework TutorialDouglas C. Schmidt#59Interpreter class behavioralStructure

IntentGiven a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language ApplicabilityWhen the grammar is simple & relatively stableEfficiency is not a critical concern

e.g., Numbere.g., Symbole.g., Operator, Add, Subtract, Divide, Multiply, etc.Pattern & Framework TutorialDouglas C. Schmidt#60ConsequencesSimple grammars are easy to change & extend, e.g., all rules represented by distinct classes in an orderly mannerAdding another rule adds another classComplex grammars are hard to implement & maintain, e.g., more interdependent rules yield more interdependent classesImplementationExpress the language rules, one per classAlternations, repetitions, or sequences expressed as nonterminal expresssionsLiteral translations expressed as terminal expressionsCreate interpret method to lead the context through the interpretation classesInterpreter class behavioralKnown UsesText editors &Web browsers use Interpreter to lay out documents & check spellingFor example, an equation in TeX is represented as a tree where internal nodes are operators, e.g. square root, & leaves are variablesPattern & Framework TutorialDouglas C. Schmidt#61

Builder object creationalIntentSeparate the construction of a complex object from its representation so that the same construction process can create different representations ApplicabilityNeed to isolate knowledge of the creation of a complex object from its parts Need to allow different implementations/interfaces of an object's parts Structuree.g., Symbole.g., Number, Operator, Add, Subtract, etc.e.g., Interpretere.g., Leaf_Node, Composite_Add_Node, etc.Pattern & Framework TutorialDouglas C. Schmidt#62Builder object creationalConsequencesCan vary a product's internal representation Isolates code for construction & representation Finer control over the construction processMay involve a lot of classesImplementationThe Builder pattern is basically a Factory pattern with a missionA Builder pattern implementation exposes itself as a factory, but goes beyond the factory implementation in that various implementations are wired togetherKnown UsesACE Service Configurator frameworkPattern & Framework TutorialDouglas C. Schmidt#63Summary of Tree Structure & Creation PatternsThere are many classes, but only a handful of patterns involved in this designCompositeCompositeBuilderInterpreterExpression_Tree_ContextExpression_TreeInterpreterInterpreter_ContextSymbolOperatorUnary_OperatorNumberSubstractAddNegateMultiplyDivideComponent_NodeComposite_Binary_NodeComposite_Unary_NodeLeaf_NodeComposite_Substract_NodeComposite_Add_NodeComposite_Negate_NodeComposite_Multiply_NodeComposite_Divide_Node>>>>Pattern & Framework TutorialDouglas C. Schmidt#64VisitorIteratorBridgeExpression_TreeComponent_NodeVisitorEvaluation_Visitorstd::stackPrint_VisitorExpression_Tree_IteratorExpression_Tree_Iterator_ImplPre_Order_Expression_Tree_Iterator_ImplIn_Order_Expression_Tree_Iterator_ImplPost_Order_Expression_Tree_Iterator_ImplLevel_Order_Expression_Tree_Iterator_ImplLQueueOverview of Tree Traversal Patterns>>Purpose: Traverse the expression tree & perform desired operationsPatterns extensibly decouple structure of expression tree from operations on itPattern & Framework TutorialDouglas C. Schmidt#65Encapsulating Variability & Simplifying Memory ManagmentGoalsHide many sources of variability in expression tree construction & useSimplify 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

Must ensure that exceptions dont cause memory leaksfor (Expression_Tree::iterator iter = tree.begin (); iter != tree.end (); ++iter) (*iter).accept (print_visitor);Pattern & Framework TutorialDouglas C. Schmidt#66Solution: 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 variabilityThe public interface class can perform reference counting of implementation object(s) to automate memory managementAn Abstract Factory can produce the right implementation (as seen later)Pattern & Framework TutorialDouglas C. Schmidt#67Expression_TreeExpression_Tree (void)Expression_Tree (Component_Node *root)Expression_Tree (const Expression_Tree &t)voidoperator= (const Expression_Tree &t)~Expression_Tree (void)Component_Node *get_root (void)boolis_null (void) const const intitem (void) const Expression_Treeleft (void)Expression_Treeright (void)iteratorbegin (const std::string &traversal_order)iteratorend (const std::string &traversal_order)const_iteratorbegin (const std::string &traversal_order) const const_iteratorend (const std::string &traversal_order) const Interface for Composite pattern used to contain all nodes in expression treeCommonality: Provides a common interface for expression tree operationsVariability: The contents of the expression tree nodes can vary depending on the expressionInterface:Pattern & Framework TutorialDouglas C. Schmidt#68Bridge object structuralIntentSeparate a (logical) abstraction interface from its (physical) implementation(s)ApplicabilityWhen interface & implementation should vary independentlyRequire a uniform interface to interchangeable class hierarchiesStructure

Pattern & Framework TutorialDouglas C. Schmidt#69Consequencesabstraction interface & implementation are independentimplementations can vary dynamicallyCan be used transparently with STL algorithms & containersone-size-fits-all Abstraction & Implementor interfacesImplementationsharing Implementors & reference countingSee reusable Refcounter template class (based on STL/boost shared_pointer)creating the right Implementor (often use factories)Known UsesET++ Window/WindowPortlibg++ Set/{LinkedList, HashTable}AWT Component/ComponentPeerBridge object structuralPattern & Framework TutorialDouglas C. Schmidt#70Tree Printing & EvaluationGoals:create a framework for performing algorithms that affect nodes in a tree

Constraints/forces:support multiple algorithms that can act on the expression treedont tightly couple algorithms with expression tree structuree.g., dont have print & evaluate methods in the node classes

LeafNodesBinaryNodesUnaryNodeAlgo 1: Print all the values of the nodes in the treeAlgo 2: Evaluate the yield of the nodes in the treePattern & Framework TutorialDouglas C. Schmidt#71Solution: Encapsulate Traversal

LeafNodesUnaryNodeExpression_Tree_IteratorExpression_Tree_Iterator_ImplLevel_Order_Expression_Tree_Iterator_ImplPre_Order_Expression_Tree_Iterator_ImplIn_Order_Expression_Tree_Iterator_ImplPost_Order_Expression_Tree_Iterator_ImplIteratorencapsulates a traversal algorithm without exposing representation details to callers e.g.,in-order iterator = -5*(3+4)pre-order iterator = *-5+34post-order iterator = 5-34+*level-order iterator = *-+534

Note use of the Bridge pattern to encapsulate variabilityPattern & Framework TutorialDouglas C. Schmidt#72Expression_Tree_IteratorExpression_Tree_Iterator (const Expression_Tree_Iterator &)Expression_Tree_Iterator (Expression_Tree_Iterator_Impl *)Expression_Treeoperator * (void)const Expression_Treeoperator * (void) const Expression_Tree_Iterator &operator++ (void)Expression_Tree_Iteratoroperator++ (int)booloperator== (const Expression_Tree_Iterator &rhs)booloperator!= (const Expression_Tree_Iterator &rhs)Interface:Commonality: Provides a common interface for expression tree iterators that conforms to the standard STL iterator interfaceVariability: Can be configured with specific expression tree iterator algorithms via the Bridge & Abstract Factory patternsInterface for Iterator pattern that traverses all nodes in tree expression See Expression_Tree_State.cpp for example usagePattern & Framework TutorialDouglas C. Schmidt#73Expression_Tree_Iterator_ImplInterface:Commonality: Provides a common interface for implementing expression tree iterators that conforms to the standard STL iterator interfaceVariability: Can be subclasses to define various algorithms for accessing nodes in the expression trees in a particular traversal orderImplementation of the Iterator pattern that is used to define the various iterations algorithms that can be performed to traverse the expression treeExpression_Tree_Iterator_Impl (const Expression_Tree &tree)virtual~Expression_Tree_Iterator_Impl (void)virtual Expression_Treeoperator * (void) =0virtual const Expression_Treeoperator * (void) const =0virtual voidoperator++ (void)=0virtual booloperator== (const Expression_Tree_Iterator_Impl &rhs) const =0virtual booloperator!= (const Expression_Tree_Iterator_Impl &rhs) const =0virtual Expression_Tree_Iterator_Impl *clone (void)=0Pattern & Framework TutorialDouglas C. Schmidt#74Iterator object behavioralIntentaccess elements of a aggregate (container) without exposing its representationApplicabilityrequire multiple traversal algorithms over an aggregaterequire a uniform traversal interface over different aggregateswhen aggregate classes & traversal algorithm must vary independentlyStructure

Pattern & Framework TutorialDouglas C. Schmidt#75Comparing STL Iterators with GoF Iteratorsfor (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;STL iterators have value-semantics, e.g.:The Bridge pattern simplifies use of STL iterators in expression tree application Pattern & Framework TutorialDouglas C. Schmidt#76Consequencesflexibility: aggregate & traversal are independentmultiple iterators & multiple traversal algorithmsadditional communication overhead between iterator & aggregateThis is particularly problematic for iterators in concurrent or distributed systemsImplementationinternal versus external iteratorsviolating the object structures encapsulationrobust iteratorssynchronization overhead in multi-threaded programsbatching in distributed & concurrent programsKnown UsesC++ STL iteratorsC++11 range-based for loopsJDK Enumeration, IteratorUnidraw IteratorIterator object behavioralPattern & Framework TutorialDouglas C. Schmidt#77VisitorDefines action(s) at each step of traversal & avoids wiring action(s) in nodesIterator calls nodess accept(Visitor) at each node, e.g.:void Leaf_Node::accept (Visitor &v) { v.visit (*this); }accept() calls back on visitor using static polymorphismCommonality: Provides a common accept()method for all expression tree nodes & common visit()method for all visitor subclassesVariability: Can be subclassed to define specific behaviors for the visitors & nodesInterface:virtual voidvisit (const Leaf_Node &node)=0virtual voidvisit (const Composite_Negate_Node &node)=0virtual voidvisit (const Composite_Add_Node &node)=0virtual voidvisit (const Composite_Subtract_Node &node)=0virtual voidvisit (const Composite_Divide_Node &node)=0virtual voidvisit (const Composite_Multiply_Node &node)=0

Pattern & Framework TutorialDouglas C. Schmidt#78Print_VisitorPrints character code or value for each node

Can be combined with any traversal algorithm, e.g.: 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};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);See Expression_Tree_State.cpp for example usagePattern & Framework TutorialDouglas C. Schmidt#79Print_Visitor Interaction Diagram

The iterator controls the order in which accept()is called on each node in the compositionaccept()then visits the node to perform the desired print action accept(print_visitor) accept(print_visitor) print_visitor Leaf_Node (5) Composite_Negate_Node coutPatterns allow adding new operations extensibly without affecting structurePattern & Framework TutorialDouglas C. Schmidt#85CommandAbstractFactoryExpression_Tree_Command_Factory_ImplExpression_Tree_Command_FactoryExpression_Tree_Event_HandlerExpression_Tree_Command>Concrete_Expression_Tree_Command_Factory_ImplExpression_Tree_Command_ImplFormat_CommandExpr_CommandPrint_CommandEval_CommandSet_CommandQuit_CommandMacro_Command*Null_CommandExpression_Tree_Context1Overview of Command & Factory PatternsPurpose: Define operations that can be performed on an expression treeThese patterns decouple creation from use & provide a uniform command APIPattern & Framework TutorialDouglas C. Schmidt#86Consolidating User OperationsGoals:support execution of user operationssupport macro commandssupport undo/redo

Constraints/forces:scattered operation implementationsConsistent memory management% tree-traversal -vformat [in-order]expr [expression]print [in-order|pre-order|post-order|level-order]eval [post-order]quit> format in-order> expr 1+2*3/2> print in-order1+2*3/2> print pre-order+1/*232> eval post-order4> quitPattern & Framework TutorialDouglas C. Schmidt#87Solution: Encapsulate Each Request w/CommandA Command encapsulatesCommand mayimplement the operations itself, orforward them to other object(s)an operation (execute())an inverse operation (unexecute())a operation for testing reversibility(boolean reversible())state for (un)doing the operationExpression_Tree_Command_ImplExpr_CommandMacro_CommandExpression_Tree_CommandFormat_CommandQuit_CommandPrint_CommandEval_CommandNote use of Bridge pattern to encapsulate variability & simplify memory managementPattern & Framework TutorialDouglas C. Schmidt#88Expression_Tree_CommandExpression_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)boolexecute (void)boolunexecute (void)Interface for Command pattern used to define a command that performs an operation on the expression tree when executedInterface:Commonality: Provides a common interface for expression tree commandsVariability: The implementations of the expression tree commands can vary depending on the operations requested by user inputPattern & Framework TutorialDouglas C. Schmidt#89List of Commands = Execution History futurepastcmdexecute()cmdunexecute()pastfutureUndo:Redo:cmdunexecute()cmdunexecute()Pattern & Framework TutorialDouglas C. Schmidt#90Command object behavioralIntentEncapsulate the request for a serviceApplicabilityto parameterize objects with an action to performto specify, queue, & execute requests at different timesfor multilevel undo/redo

Structure

Pattern & Framework TutorialDouglas C. Schmidt#91Consequencesabstracts executor of a servicesupports arbitrary-level undo-redocomposition yields macro-commandsmight result in lots of trivial command subclassesexcessive memory may be needed to support undo/redo operationsImplementationcopying a command before putting it on a history listhandling hysteresissupporting transactionsCommand object behavioralKnown UsesInterViews ActionsMacApp, Unidraw CommandsJDKs UndoableEdit, AccessibleActionEmacsMicrosoft Office toolsPattern & Framework TutorialDouglas C. Schmidt#92Consolidating Creation of VariabilitiesGoals:Simplify & centralize the creation of all variabilities in the expression tree application to ensure semantic compatibility Be extensible for future variabilitiesExpression_Tree_Command_ImplExpr_CommandMacro_CommandExpression_Tree_CommandFormat_CommandQuit_CommandPrint_CommandEval_CommandExpression_Tree_IteratorExpression_Tree_Iterator_ImplLevel_Order_Expression_Tree_Iterator_ImplPre_Order_Expression_Tree_Iterator_ImplIn_Order_Expression_Tree_Iterator_ImplPost_Order_Expression_Tree_Iterator_ImplConstraints/forces:Dont recode existing clientsAdd new variabilities without recompilingPattern & Framework TutorialDouglas C. Schmidt#93Solution: Abstract Object CreationInstead 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 goalsExpression_Tree_Command_Factory_ImplConcrete_Expression_Tree_Command_Factory_ImplExpression_Tree_Command_FactoryPattern & Framework TutorialDouglas C. Schmidt#94Expression_Tree_Command_FactoryExpression_Tree_Command_Factory (Expression_Tree_Context &tree_context)Expression_Tree_Command_Factory (const Expression_Tree_Command_Factory &f)voidoperator= (const Expression_Tree_Command_Factory &f)~Expression_Tree_Command_Factory (void)Expression_Tree_Commandmake_command (const std::string &s)Expression_Tree_Commandmake_format_command (const std::string &)Expression_Tree_Commandmake_expr_command (const std::string &)Expression_Tree_Commandmake_print_command (const std::string &)Expression_Tree_Commandmake_eval_command (const std::string &)Expression_Tree_Commandmake_quit_command (const std::string &)Expression_Tree_Commandmake_macro_command (const std::string &)Interface for Abstract Factory pattern used to create appropriate command based on string supplied by callerInterface:Commonality: Provides a common interface to create commandsVariability: The implementations of the expression tree command factory methods can vary depending on the requested commandsPattern & Framework TutorialDouglas C. Schmidt#95Factory StructureExpression_Tree_Command_Factory_ImplConcrete_Expression_Tree_Command_Factory_Implmake_format_command()make_expr_command()make_print_command()make_eval_command()make_macro_command()make_quit_command()Expression_Tree_Command_ImplPrint_CommandExpression_Tree_CommandMacro_CommandFormat_CommandExpr_CommandEval_CommandNote use of Bridge pattern to encapsulate variability & simplify memory managementExpression_Tree_Command_FactoryQuit_CommandPattern & Framework TutorialDouglas C. Schmidt#96Factory Method class creationalIntentProvide an interface for creating an object, but leave choice of objects concrete type to a subclassApplicabilitywhen a class cannot anticipate the objects it must create or a class wants its subclasses to specify the objects it createsStructure

Pattern & Framework TutorialDouglas C. Schmidt#97Consequences+By avoiding to specify the class name of the concrete class &the details of its creation the client code has become more flexible+The client is only dependent on the interface- Construction of objects requires one additional class in some casesImplementationThere are two choices hereThe 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 parameterFactory Method class creationalKnown UsesInterViews KitsET++ WindowSystemAWT ToolkitThe ACE ORB (TAO)BREWUNIX open() syscallPattern & Framework TutorialDouglas C. Schmidt#98Abstract Factory object creationalIntentcreate families of related objects without specifying subclass namesApplicabilitywhen clients cannot anticipate groups of classes to instantiate

Structure

See Uninitialized_State_Factory & Expression_Tree_Event_Handler for Factory pattern variantsPattern & Framework TutorialDouglas C. Schmidt#99Consequencesflexibility: removes type (i.e., subclass) dependencies from clientsabstraction & semantic checking: hides products compositionhard to extend factory interface to create new products

Implementationparameterization as a way of controlling interface sizeconfiguration with Prototypes, i.e., determines who creates the factoriesabstract factories are essentially groups of factory methodsAbstract Factory object creationalKnown UsesInterViews KitsET++ WindowSystemAWT ToolkitThe ACE ORB (TAO)Pattern & Framework TutorialDouglas C. Schmidt#100CommandAbstractFactoryExpression_Tree_Command_Factory_ImplExpression_Tree_Command_FactoryExpression_Tree_Event_HandlerExpression_Tree_Command>Concrete_Expression_Tree_Command_Factory_ImplExpression_Tree_Command_ImplFormat_CommandExpr_CommandPrint_CommandEval_CommandSet_CommandQuit_CommandMacro_Command*Null_CommandExpression_Tree_Context1Summary of Command & Factory PatternsPatterns enable new commands extensibly by adding new factory methodsPattern & Framework TutorialDouglas C. Schmidt#101StateExpression_Tree_ContextExpression_Tree_StateUninitialized_StatePre_Order_Uninitialized_StatePre_Order_Initialized_StatePost_Order_Uninitialized_StatePost_Order_Initialized_StateIn_Order_Uninitialized_StateIn_Order_Initialized_StateLevel_Order_Uninitialized_StateLevel_Order_Initialized_StateInterpreter>Overview of State PatternPurpose: Ensure user commands are performed in the correct orderPattern organizes the correct processing of user commands Pattern & Framework TutorialDouglas C. Schmidt#102Ensuring Correct Protocol for CommandsGoals:Ensure that users follow the correct protocol when entering commandsConstraints/forces:Must consider context of previous commands to determine protocol conformance, e.g.,format must be called firstexpr must be called before print or evalPrint & eval can be called in any order% tree-traversal -vformat [in-order]expr [expression]print [in-order|pre-order|post-order|level-order]eval [post-order]quit> format in-order> print in-orderError: Expression_Tree_State::print called in invalid stateProtocol violationPattern & Framework TutorialDouglas C. Schmidt#103Solution: Encapsulate Command History as StatesThe handling of a user command depends on the history of prior commandsThis history can be represented as a state machine

Uninitialized State*_Order_ Uninitialized State*_Order_ Initialized Stateformat()make_tree()print()eval()make_tree()format()quit()Pattern & Framework TutorialDouglas C. Schmidt#104Solution: Encapsulate Command History as StatesNote use of Bridge pattern to encapsulate variability & simplify memory management

Expression_Tree_ContextThe state machine can be encoded using various subclasses that enforce the correct protocol for user commands

Pattern & Framework TutorialDouglas C. Schmidt#105Expression_Tree_ContextInterface for State pattern used to ensure that commands are invoked according to the correct protocolInterface:Commonality: Provides a common interface for ensuring that expression tree commands are invoked according to the correct protocolVariability: The implementations& correct functioningof the expression tree commands can vary depending on the requested operations & the current statevoidformat (const std::string &new_format)voidmake_tree (const std::string &expression)voidprint (const std::string &format)voidevaluate (const std::string &format)Expression_Tree_State *state (void) const voidstate (Expression_Tree_State *new_state)Expression_Tree &tree (void)voidtree (const Expression_Tree &new_tree)Pattern & Framework TutorialDouglas C. Schmidt#106Expression_Tree_StateImplementation of the State pattern that is used to define the various states that affect how users operations are processedInterface:Commonality: Provides a common interface for ensuring that expression tree commands are invoked according to the correct protocolVariability: The implementations& correct functioningof the expression tree commands can vary depending on the requested operations & the current statevirtual voidformat (Expression_Tree_Context &context, const std::string &new_format)virtual voidmake_tree (Expression_Tree_Context &context, const std::string &expression)virtual voidprint (Expression_Tree_Context &context, const std::string &format)virtual voidevaluate (Expression_Tree_Context &context, const std::string &format)Pattern & Framework TutorialDouglas C. Schmidt#107State object behavioralIntentAllow an object to alter its behavior when its internal state changesthe object will appear to change its classApplicabilityWhen an object must change its behavior at run-time depending on which state it is in When several operations have the same large multipart conditional structure that depends on the object's state Structure

Pattern & Framework TutorialDouglas C. Schmidt#108ConsequencesIt localizes state-specific behavior & partitions behavior for different states It makes state transitions explicit State objects can be sharedCan result in lots of subclasses that are hard to understandImplementationWho defines state transitions?Consider using table-based alternativesCreating & destroying state objectsKnown UsesThe State pattern & its application to TCP connection protocols are characterized in: Johnson, R.E. & J. Zweig. Delegation in C++. Journal of Object-Oriented Programming, 4(11):22-35, November 1991Unidraw & Hotdraw drawing toolsState object behavioralPattern & Framework TutorialDouglas C. Schmidt#109StateExpression_Tree_ContextExpression_Tree_StateUninitialized_StatePre_Order_Uninitialized_StatePre_Order_Initialized_StatePost_Order_Uninitialized_StatePost_Order_Initialized_StateIn_Order_Uninitialized_StateIn_Order_Initialized_StateLevel_Order_Uninitialized_StateLevel_Order_Initialized_StateInterpreter>Summary of State PatternPattern makes the correct ordering of user commands explicit in the design Pattern & Framework TutorialDouglas C. Schmidt#110Strategy & Template MethodReactorSingletonOverview of Application Structure PatternsExpression_Tree_Command_FactoryExpression_Tree_Event_HandlerExpression_Tree_CommandExpression_Tree_ContextVerbose_Expression_Tree_Event_HandlerMacro_Expression_Tree_Event_Handler>Event_HandlerOptionsReactorPatterns simplify processing of user options & operation modesPurpose: Provide the overall structure of the event-driven applicationPattern & Framework TutorialDouglas C. Schmidt#111Driving the Application Event FlowGoals:Decouple expression tree application from the context in which it runsSupport inversion of controlConstraints/forces:Dont recode existing clientsAdd new event handles without recompilingSTL algorithmsReactor GUIDATABASE NETWORKINGEXPRESSION TREEFUNCTIONALITYCALLBACKSINVOKESPattern & Framework TutorialDouglas C. Schmidt#112Solution: Separate Event Handling from Event Infrastructure

Reactorregister_handler()remove_handler()run_event_loop()end_event_loop()Create a reactor to detect input on various sources of events & then demux & dispatch the events to the appropriate event handlersCreate concrete event handlers that perform the various operational modes of the expression tree applicationRegister the concrete event handlers with the reactorRun the reactors event loop to drive the application event flowPattern & Framework TutorialDouglas C. Schmidt#113Reactor & Event HandlerAn object-oriented event demultiplexor & dispatcher of event handler callback methods in response to various types of eventsInterface:Commonality: Provides a common interface for managing & processing events via callbacks to abstract event handlersVariability: Concrete implementations of the Reactor & Event_Handlers can be tailored to a wide range of OS demuxing mechanisms & application-specific concrete event handling behaviors~Reactor (void)voidrun_event_loop (void)voidend_event_loop (void)voidregister_input_handler (Event_Handler *event_handler)voidremove_input_handler (Event_Handler *event_handler)static Reactor *instance (void) virtual void~Event_Handler (void) =0virtual voiddelete_this (void)virtual voidhandle_input (void)=0usesPattern & Framework TutorialDouglas C. Schmidt#114Reactor Interactions: Main Program: Exression_TreeEvent Handler: Reactor: Synchronous EventDemultiplexerregister_handler()get_handle()handle_events()select()handle_event()HandleHandlesHandlesCon. EventHandlerEventsservice()eventInitialize phaseEvent handling phaseObservationsNote inversion of controlAlso note how long-running event handlers can degrade the QoS since callbacks steal the reactors thread! See main.cpp for example of using Reactor to drive event loopPattern & Framework TutorialDouglas C. Schmidt#115Reactor object behavioralIntentallows event-driven applications to demultiplex & dispatch service requests that are delivered to an application from one or more clients ApplicabilityNeed to decouple event handling from event detecting/demuxing/dispatchingWhen multiple sources of events must be handled in a single threadStructureHandleownsdispatches*notifies**handle set Reactor

handle_events()register_handler()remove_handler()

Event Handler

handle_event ()get_handle()Concrete Event Handler A

handle_event ()get_handle()Concrete Event Handler B

handle_event ()get_handle()SynchronousEvent Demuxer

select ()

Pattern & Framework TutorialDouglas C. Schmidt#116ConsequencesSeparation of concerns & portabilitySimplify concurrency controlNon-preemptive

ImplementationDecouple event demuxing mechanisms from event dispatchingHandle many different types of events, e.g., input/output events, signals, timers, etc.Reactor object behavioralKnown UsesInterViews KitsET++ WindowSystemAWT ToolkitX Windows XtACE & The ACE ORB (TAO)Pattern & Framework TutorialDouglas C. Schmidt#117Supporting Multiple Operation ModesGoals:Minimize effort required to support multiple modes of operation e.g., verbose & succinct

Constraints/forces:support multiple operational modesdont tightly couple the operational modes with the program structure to enable future enhancements% tree-traversal -vformat [in-order]expr [expression]print [in-order|pre-order|post-order|level-order]eval [post-order]quit> format in-order> expr 1+4*3/2> eval post-order7> quit

% tree-traversal> 1+4*3/27

Verbose modeSuccinct modePattern & Framework TutorialDouglas C. Schmidt#118Solution: Encapsulate Algorithm VariabilityExpression_Tree_Event_Handlerhandle_input()prompt_user()get_input()make_command()execute_command()Event_HandlerVerbose_Expression_Tree_Event_Handlerprompt_user()make_command()Macro_Command_Expression_Tree_Event_Handlerprompt_user()make_command()void handle_input (void) { // template method prompt_user (); // hook method

std::string input;

if (get_input (input) == false) // hook method Reactor::instance ()->end_event_loop ();

Expression_Tree_Command command = make_command (input); // hook method

if (!execute_command (command)) // hook method Reactor::instance ()->end_event_loop ();}Expression_Tree_Command make_command (const std::string &input) { return command_factory_.make_macro_command (input);}Expression_Tree_Command make_command (const std::string &input) { return command_factory_.make_command (input);}Implement algorithm once in base class & let subclasses define variant partsPattern & Framework TutorialDouglas C. Schmidt#119Expression_Tree_Event_HandlerProvides an abstract interface for handling input events associated with the expression tree applicationInterface:Commonality: Provides a common interface for handling user input events & commandsVariability: Subclasses implement various operational modes, e.g., verbose vs. succinct modevirtual voidhandle_input (void)static Expression_Tree_Event_Handler *make_handler (bool verbose)virtual voidprompt_user (void)=0virtual boolget_input (std::string &)virtual Expression_Tree_Commandmake_command (const std::string &input)=0virtual boolexecute_command (Expression_Tree_Command &)Note make_handler() factory method variantPattern & Framework TutorialDouglas C. Schmidt#120Template Method class behavioralIntentProvide a skeleton of an algorithm in a method, deferring some steps to subclassesApplicabilityImplement invariant aspects of an algorithm once & let subclasses define variant partsLocalize common behavior in a class to increase code reuseControl subclass extensionsStructure

Pattern & Framework TutorialDouglas C. Schmidt#121Template Method class behavioralConsequencesLeads to inversion of control (Hollywood principle: don't call us we'll call you)Promotes code reuseLets you enforce overriding rulesMust subclass to specialize behavior (cf. Strategy pattern)ImplementationVirtual vs. non-virtual template methodFew vs. lots of primitive operations (hook method)Naming conventions (do_*() prefix)Known UsesInterViews KitsET++ WindowSystemAWT ToolkitACE & The ACE ORB (TAO)Pattern & Framework TutorialDouglas C. Schmidt#122Strategy object behavioralIntentdefine a family of algorithms, encapsulate each one, & make them interchangeable to let clients & algorithms vary independentlyApplicabilitywhen an object should be configurable with one of many algorithms,and all algorithms can be encapsulated,and one interface covers all encapsulations Structure

Pattern & Framework TutorialDouglas C. Schmidt#123Consequencesgreater flexibility, reusecan change algorithms dynamicallystrategy creation & communication overheadinflexible Strategy interfacesemantic incompatibility of multiple strategies used togetherImplementationexchanging information between a Strategy & its contextstatic strategy selection via parameterized typesStrategy object behavioralKnown UsesInterViews text formattingRTL register allocation & scheduling strategiesET++SwapsManager calculation enginesThe ACE ORB (TAO) Real-time CORBA middlewareSee AlsoBridge pattern (object structural)Pattern & Framework TutorialDouglas C. Schmidt#124Comparing Strategy with Template MethodStrategyProvides for clean separation between components through interfacesAllows for dynamic compositionAllows for flexible mixing & matching of featuresHas the overhead of forwardingSuffers from the identity crisisLeads to more fragmentationTemplate MethodNo explicit forwarding necessaryClose coupling between subclass(es) & base classInheritance hierarchies are static & cannot be reconfigured at runtimeAdding features through subclassing may lead to a combinatorial explosionBeware of overusing inheritanceinheritance is not always the best choiceDeep inheritance hierarchy (6 levels & more) in your application is a red flagStrategy is commonly used for blackbox frameworks Template Method is commonly used for whitebox frameworksPattern & Framework TutorialDouglas C. Schmidt#125Strategy & Template MethodReactorSingletonSummary of Application Structure PatternsExpression_Tree_Command_FactoryExpression_Tree_Event_HandlerExpression_Tree_CommandExpression_Tree_ContextVerbose_Expression_Tree_Event_HandlerMacro_Expression_Tree_Event_Handler>Event_HandlerOptionsReactorPatterns make it easier to support various modes of operationsPattern & Framework TutorialDouglas C. Schmidt#126Implementing STL Iterator SemanticsGoals:Ensure the proper semantics of post-increment operations for STL-based Expression_Tree_Iterator objectsConstraints/forces:STL pre-increment operations are easy to implement since they simply increment the value & return *this, e.g.,iterator &operator++ (void) { ++...; return *this; }STL post-increment operations are more complicated, however, since must make/return a copy of the existing value of the iterator before incrementing its value, e.g.,iterator operator++ (int) { iterator temp = copy_*this; ++...; return temp; }Since our Expression_Tree_Iterator objects use the Bridge pattern it is tricky to implement the copy_*this step above in a generic wayPattern & Framework TutorialDouglas C. Schmidt#127Solution: Clone a New Instance From a Prototypical InstanceExpression_Tree_Iterator operator++ (int)Expression_Tree_Iterator_Implclone()Level_Order_Expression_Tree_Iterator_Implclone()Pre_Order_Expression_Tree_Iterator_Implclone()In_Order_Expression_Tree_Iterator_Implclone()Post_Order_Expression_Tree_Iterator_Implclone()iteratorExpression_Tree_Iterator::operator++ (int){ iterator temp (impl_->clone ()); ++(*impl_); return temp;}impl_Note use of Bridge pattern to encapsulate variability & simplify memory managementPattern & Framework TutorialDouglas C. Schmidt#128Expression_Tree_Iterator_ImplImplementation of Iterator pattern used to define various iterations algorithms that can be performed to traverse an expression treeExpression_Tree_Iterator_Impl (const Expression_Tree &tree)virtual Component_Node *operator * (void)=0 voidoperator++ (void)=0virtual booloperator== (const Expression_Tree_ Iterator_Impl &) const=0virtual booloperator!= (const Expression_Tree_ Iterator_Impl &) const=0virtual Expression_Tree_Iterator_Impl *clone (void)=0Interface:Commonality: Provides a common interface for expression tree iterator implementationsVariability: Each subclass implements the clone() method to return a deep copy of itselfAs a general rule its better to say ++iter than iter++Pattern & Framework TutorialDouglas C. Schmidt#129Prototype object creationalIntentSpecify the kinds of objects to create using a prototypical instance & create new objects by copying this prototype Applicabilitywhen a system should be independent of how its products are created, composed, & represented when the classes to instantiate are specified at run-time; or

Structure

Pattern & Framework TutorialDouglas C. Schmidt#130Consequencescan add & remove classes at runtime by cloning them as neededreduced subclassing minimizes/eliminates need for lexical dependencies at run-timeevery class that used as a prototype must itself be instantiated classes that have circular references to other classes cannot really be clonedImplementationUse prototype managerShallow vs. deep copiesInitializing clone internal state within a uniform interfacePrototype object creationalKnown UsesThe first widely known application of the Prototype pattern in an object-oriented language was in ThingLab Coplien describes idioms related to the Prototype pattern for C++ & gives many examples & variationsEtgdb debugger for ET++ The music editor example is based on the Unidraw drawing frameworkPattern & Framework TutorialDouglas C. Schmidt#131Part III: Wrap-Up

Pattern & Framework TutorialDouglas C. Schmidt#132Life Beyond GoF Patterns

www.cs.wustl.edu/~schmidt/PDF/ieee-patterns.pdf

Pattern & Framework TutorialDouglas C. Schmidt#133Stand-alone patterns are point solutions to relatively bounded problems that arise within specific contextse.g., see the PLoPD books

Any significant software design inevitably includes many patterns, however, which means that a stand-alone pattern unusual in practiceA common presentation of multiple patterns is in the form of a pattern collectione.g., the GoF & POSA1 books

Overview of Pattern Collections

Pattern & Framework TutorialDouglas C. Schmidt#134Overview of Pattern RelationshipsPatterns representing the foci for discussion, point solutions, or localized design ideas can be used in isolation with some successPatterns are generally gregarious, however, in that they form relationships with other patternsFour of the most common types of pattern relationships include:Patterns complements, where one pattern provides the missing ingredient needed by another or where one pattern contrasts with another by providing an alternative solution to a related problemPattern compounds capture recurring subcommunities of patterns that are common & identifiable enough that they can be treated as a single decision in response to a recurring problemPattern sequences generalize the progression of patterns & the way a design can be established by joining predecessor patterns to form part of the context of each successive patternPattern languages define a vocabulary for talking about software development problems & provide a process for the orderly resolution of these problemsPattern & Framework TutorialDouglas C. Schmidt#135

Overview of Pattern ComplementsOne pattern provides missing ingredient needed by anotheror where one pattern competes with another by providing an alternative solution to a related problemto make resulting designs more complete & balanced, e.g.:Disposal Method complements Factory Method by addressing object destruction & creation, respectively, in the same design

Batch Method competes with Iterator by accessing the elements of an aggregate in bulk, reducing roundtrip network costs

Pattern & Framework TutorialDouglas C. Schmidt#136Overview of Pattern CompoundsPattern compounds capture recurring subcommunities of patterns that are common & identifiable enough that they can be treated as a single decision in response to a recurring problemFor example, Batch Iterator brings together two complementary patterns, Iterator & Batch Method, to address the problem of remotely accessing the elements of aggregates with large numbers of elements A Batch Iterator refines the position-based traversal of an Iterator with a Batch Method for bulk access of many, but not all, elements

Pattern & Framework TutorialDouglas C. Schmidt#137Overview of Pattern SequencesPattern sequences generalize the progression of patterns & the way a design can be established by joining predecessor patterns to form the context of each successive patternA pattern sequence captures the unfolding of a design or situation, pattern-by-pattern e.g., POSA2 & POSA4 present pattern sequences for communication middleware

Pattern & Framework TutorialDouglas C. Schmidt#138Overview of Pattern SequencesPattern sequences generalize the progression of patterns & the way a design can be established by joining predecessor patterns to form the context of each successive patternA pattern sequence captures the unfolding of a design or situation, pattern-by-pattern e.g., POSA3 presents pattern sequences for resource management

Resource LifecycleManagerCachingPoolingLeasingEvictorPartialAcquisitionLazyAcquisitionCoordinatorLookupEagerAcquisitionPerformanceScalabilityConsistencyStabilityFlexibilityPredictabilityPattern & Framework TutorialDouglas C. Schmidt#139Overview of Pattern Languages

Pattern languages define a vocabulary for talking about software development problems & provide a process for the orderly resolution of these problemsFor example, the POSA4 pattern language for distributed computing includes 114 patterns grouped into 13 problem areasEach problem area addresses a specific technical topic related to building distributed systemsPOSA5 describes key concepts of pattern languages

Pattern & Framework TutorialDouglas C. Schmidt#140Observations on Applying Patterns & FrameworksPatterns & frameworks supportdesign/implementation at a more abstract leveltreat many class/object interactions as a unitoften beneficial after initial designtargets for class refactoringsVariation-oriented design/implementationconsider what design aspects are variableidentify applicable pattern(s)vary patterns to evaluate tradeoffsrepeatPatterns are applicable in all stages of the OO lifecycleanalysis, design, & reviewsrealization & documentationreuse & refactoringPatterns often equated with OO languages, but many also apply to C Pattern & Framework TutorialDouglas C. Schmidt#141Pattern & framework design even harder than OO design!Dont apply patterns & frameworks blindlyAdded indirection can yield increased complexity, costUnderstand patterns to learn how to better develop/use frameworksResist branding everything a patternArticulate specific benefitsDemonstrate wide applicabilityFind at least three existing examples from code other than your own!

Caveats to Keep in MindPattern & Framework TutorialDouglas C. Schmidt#142Concluding RemarksPatterns & frameworks promoteIntegrated design & implementation reuseuniform design vocabularyunderstanding, restructuring, & team communicationa basis for automationa new way to think about software design & implementation

Theres much more to patterns than just the GoF, however!!!!Pattern & Framework TutorialDouglas C. Schmidt#143Pattern ReferencesBooksTimeless Way of Building, Alexander, ISBN 0-19-502402-8A Pattern Language, Alexander, 0-19-501-919-9Design Patterns, Gamma, et al., 0-201-63361-2 CD version 0-201-63498-8Pattern-Oriented Software Architecture, Vol. 1, Buschmann, et al., 0-471-95869-7Pattern-Oriented Software Architecture, Vol. 2, Schmidt, et al., 0-471-60695-2Pattern-Oriented Software Architecture, Vol. 3, Jain & Kircher, 0-470-84525-2Pattern-Oriented Software Architecture, Vol. 4, Buschmann, et al., 0-470-05902-8 Pattern-Oriented Software Architecture, Vol. 5, Buschmann, et al., 0-471-48648-5 Pattern & Framework TutorialDouglas C. Schmidt#144Pattern References (contd)More BooksAnalysis Patterns, Fowler; 0-201-89542-0 Concurrent Programming in Java, 2nd ed., Lea, 0-201-31009-0 Pattern Languages of Program DesignVol. 1, Coplien, et al., eds., ISBN 0-201-60734-4Vol. 2, Vlissides, et al., eds., 0-201-89527-7Vol. 3, Martin, et al., eds., 0-201-31011-2Vol. 4, Harrison, et al., eds., 0-201-43304-4Vol. 5, Manolescu, et al., eds., 0-321-32194-4 AntiPatterns, Brown, et al., 0-471-19713-0Applying UML & Patterns, 2nd ed., Larman, 0-13-092569-1Pattern Hatching, Vlissides, 0-201-43293-5The Pattern Almanac 2000, Rising, 0-201-61567-3Pattern & Framework TutorialDouglas C. Schmidt#145Pattern References (contd)Even More BooksSmall Memory Software, Noble & Weir, 0-201-59607-5Microsoft Visual Basic Design Patterns, Stamatakis, 1-572-31957-7Smalltalk Best Practice Patterns, Beck; 0-13-476904-XThe Design Patterns Smalltalk Companion, Alpert, et al., 0-201-18462-1Modern C++ Design, Alexandrescu, ISBN 0-201-70431-5Building Parsers with Java, Metsker, 0-201-71962-2Core J2EE Patterns, Alur, et al., 0-130-64884-1 Design Patterns Explained, Shalloway & Trott, 0-201-71594-5The Joy of Patterns, Goldfedder, 0-201-65759-7The Manager Pool, Olson & Stimmel, 0-201-72583-5

Pattern & Framework TutorialDouglas C. Schmidt#146Pattern References (contd)Early PapersObject-Oriented Patterns, P. Coad; Comm. of the ACM, 9/92Documenting Frameworks using Patterns, R. Johnson; OOPSLA 92Design Patterns: Abstraction & Reuse of Object-Oriented Design, Gamma, Helm, Johnson, Vlissides, ECOOP 93

ArticlesJava Report, Java Pro, JOOP, Dr. Dobbs Journal, Java Developers Journal, C++ Report

How to Study Patterns http://www.industriallogic.com/papers/learning.html

Pattern & Framework TutorialDouglas C. Schmidt#147Pattern-Oriented ConferencesPLoP 2011: Pattern Languages of ProgramsOctober 2011, Collocated with SPLASH (formerly OOPSLA)EuroPLoP 2012, July 2012, Kloster Irsee, Germany

See hillside.net/conferences/ forup-to-the-minute infoPattern & Framework TutorialDouglas C. Schmidt#148Mailing [email protected]: present & refine [email protected]: general discussion [email protected]: discussion on Design [email protected]: discussion on Pattern-Oriented Software [email protected]: discussion on user interface [email protected]: discussion on patterns for business [email protected]: discussion on patterns for distributed systems

See http://hillside.net/patterns/mailing.htm for an up-to-date list.Pattern & Framework TutorialDouglas C. Schmidt#149