pattern-examples4

pattern-examples4 - OO Pattern Examples Case Studies Using...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: OO Pattern Examples Case Studies Using Patterns Douglas C. Schmidt Object-Oriented Design Case Studies with Patterns & C++ Professor [email protected] www.dre.vanderbilt.edu schmidt Douglas C. Schmidt Department of EECS Vanderbilt University 615 343-8197 The following slides describe several case studies using C++ & patterns to build highly extensible software The examples include 1. Expression Tree e.g., Adapter, Factory, Bridge 2. System Sort e.g., Facade, Adapter, Iterator, Singleton, Factory Method, Strategy, Bridge 3. Sort Veri er e.g., Strategy, Factory Method, Facade, Iterator, Singleton Vanderbilt University 1 OO Pattern Examples Case Study: Expression Tree Evaluator Douglas C. Schmidt OO Pattern Examples Expression Tree Diagram Douglas C. Schmidt The following inheritance & dynamic binding example constructs expression trees Expression trees consist of nodes containing operators & operands Operators have di erent precedence levels, di erent associativities, & di erent arities, e.g., Multiplication takes precedence over addition The multiplication operator has two arguments, whereas unary minus operator has only one Operands are integers, doubles, variables, etc. We'll just handle integers in this example . . . _ UNARY NODE * + 5 3 INTEGER NODES BINARY NODES 4 4 Vanderbilt University 2 Vanderbilt University 3 use_ tag_ op_ num_ unary_ binary_ MEMORY LAYOUT Vanderbilt University Tree Node Vanderbilt University OO Pattern Examples OO Pattern Examples 1 1|2 CLASS RELATIONSHIPS Tree Node Expression trees Trees may be evaluated" via di erent traversals e.g., in-order, post-order, pre-order, level-order The evaluation step may perform various operations, e.g., Traverse & print the expression tree Return the value" of the expression tree Generate code Perform semantic analysis Here's the memory layout of a struct Tree Expression Tree Behavior Memory Layout of Algorithmic Version Node object Douglas C. Schmidt 6 OO Pattern Examples Douglas C. Schmidt 4 A typical algorithmic implementation use 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_; printf "s", root- op_ 0 ; print_tree root- binary_.r_; printf ""; break; default: printf "error, unknown type n"; Print Tree Function Do OO Pattern Examples A typical algorithmic method for implementing expression trees involves using a struct union to represent data structure, e.g., typedef struct Tree_Node Tree_Node; 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 Tree_Node *unary_; struct Tree_Node *l_, *r_; binary_; c; define unary_ c.unary_ define binary_ c.binary_ ; Algorithmic Version D Vanderbilt University Vanderbilt University OO Pattern Examples Limitations with Algorithmic Approach Douglas C. Schmidt OO Pattern Examples More Limitations with Algorithmic Approach Douglas C. Schmidt Problems or limitations with the typical algorithmic approach include Little or no use of encapsulation Incomplete modeling of the application domain, which results in 1. Tight coupling between nodes & edges in union representation 2. Complexity being in algorithms rather than the data structures e.g., switch statements are used to select between various types of nodes in the expression trees Compare with binary search! 3. Data structures are passive" & functions do most processing work explicitly The program organization makes it di cult to extend, e.g., Any small changes will ripple through the entire design & implementation e.g., see the ternary" extension below Easy to make mistakes switching on type tags . . . Solution wastes space by making worst-case assumptions wrt structs & unions This is not essential, but typically occurs Note that this problem becomes worse the bigger the size of the largest item becomes! Vanderbilt University 8 Vanderbilt University 9 OO Pattern Examples OO Alternative Douglas C. Schmidt OO Pattern Examples Expression Tree Diagram Douglas C. Schmidt Contrast previous algorithmic approach with an object-oriented decomposition for the same problem: Start with OO modeling of the expression tree" application domain, e.g., go back to original picture Discover several classes involved: class Node: base class that describes expression tree vertices: class Int Node: used for implicitly converting int to Tree node class Unary Node: handles unary operators, e.g., -10, +10, !a class Binary Node: handles binary operators, e.g., a + b, 10 - 30 class Tree: glue" code that describes expression-tree edges, i.e., relations between Nodes Note, these classes model entities in the application domain i.e., nodes & edges vertices & arcs Vanderbilt University 10 Vanderbilt University _ UNARY NODE * + 5 3 INTEGER NODES BINARY NODES 4 4 11 OO Pattern Examples Relationships Between Tree & Node Classes Binary Node Unary Node Int Node Douglas C. Schmidt OO Pattern Examples Design Patterns in the Expression Tree Program Douglas C. Schmidt 1 1 Ternary Node 1 2 3 1 Tree -a has Node Factory Centralize the assembly of resources necessary to create an object e.g., decouple Node subclass initialization from use Bridge Decouple an abstraction from its implementation so that the two can vary independently e.g., printing contents of a subtree and managing memory Adapter Convert the interface of a class into another interface clients expect e.g., make Tree conform C++ iostreams 12 Vanderbilt University 13 Vanderbilt University OO Pattern Examples class Tree; Forward declaration C++ Node Interface Douglas C. Schmidt OO Pattern Examples Describes the Tree vertices class Node friend class Tree; protected: Only visible to derived classes Node : use_ 1 * pure * virtual void print std::ostream & const = 0; Important to make destructor virtual! virtual ~Node ; private: int use_; Reference counter. ; include "Node.h" Bridge class that describes the Tree edges and acts as a Factory. class Tree public: Factory operations Tree int; Tree const string &, Tree &; Tree const string &, Tree &, Tree &; Tree const Tree &t; void operator= const Tree &t; ~Tree ; void print std::ostream & const; private: Node *node_; pointer to a rooted subtree C++ Tree Interface Douglas C. Schmidt Vanderbilt University 14 Vanderbilt University 15 OO Pattern Examples C++ Int Node Interface include "Node.h" class Unary_Node : public Node public: Unary_Node const string &op, const Tree &t; virtual void print std::ostream &stream const; private: string operation_; Tree operand_; ; Douglas C. Schmidt OO Pattern Examples C++ Unary Node Interface Douglas C. Schmidt include "Node.h" class Int_Node : public Node public: Int_Node int k; virtual void print std::ostream &stream const; private: int num_; operand value. ; Vanderbilt University 16 Vanderbilt University 17 OO Pattern Examples C++ Binary Node Interface Douglas C. Schmidt include "Node.h" Do Node Node PART PART tag tag operator_ operator op op left_ left (Tree PART)) (Tree PART middle_ middle (Tree PART)) (Tree PART right_ right (Tree PART)) (Tree PART Node Node PART PART operator_ operator left_ left (Tree PART)) (Tree PART Node Node PART PART operator_ operator operand_ operand (Tree PART)) (Tree PART vptr vptr Tree use_ use Unary Node right_ right (Tree PART)) (Tree PART node_ ptr Node Node Node PART PART num_ num Binary Node Memory Layout for C++ Version OO Pattern Examples Memory layouts for di erent subclasses of Node Int_Node Ternary Node Vanderbilt University 18 Vanderbilt University class Binary_Node : public Node public: Binary_Node const string &op, const Tree &t1, const Tree &t2; virtual void print std::ostream &s const; private: const string operation_; Tree left_; Tree right_; ; OO Pattern Examples C++ Int Node Implementations include "Unary_Node.h" Unary_Node::Unary_Node const string &op, const Tree &t1 : operation_ op, operand_ t1 void Unary_Node::print std::ostream &stream const stream "" this- operation_ this- operand_ recursive call! ""; Douglas C. Schmidt OO Pattern Examples C++ Unary Node Implementations Douglas C. Schmidt include "Int_Node.h" Int_Node::Int_Node int k: num_ k void Int_Node::print std::ostream &stream const stream this- num_; Vanderbilt University 20 Vanderbilt University 21 OO Pattern Examples C++ Binary Node Implementation Douglas C. Schmidt OO Pattern Examples Initializing the Node Subclasses Douglas C. Schmidt include "Binary_Node.h" Binary_Node::Binary_Node const string &op, const Tree &t1, const Tree &t2: operation_ op, left_ t1, right_ t2 void Binary_Node::print std::ostream &stream const stream "" this- left_ recursive call " " this- operation_ " " this- right_ recursive call ""; Problem How to ensure the Node subclasses are initialized properly Forces There are di erent types of Node subclasses e.g., take di erent number & type of arguments We want to centralize initialization in one place because it is likely to change . . . Solution Use a Factory pattern to initialize the Node subclasses Vanderbilt University 22 Vanderbilt University 23 OO Pattern Examples The Factory Pattern Douglas C. Schmidt OO Pattern Examples Structure of the Factory Pattern Factory make_product() creates Product product = ... return product Douglas C. Schmidt Intent Centralize the assembly of resources necessary to create an object Decouple object creation from object use by localizing creation knowledge This pattern resolves the following forces: Decouple initialization of the Node subclasses from their subsequent use Makes it easier to change or add new Node subclasses later on e.g., Ternary nodes . . . A generalization of the GoF Factory Method pattern Vanderbilt University 24 Vanderbilt University Product 25 OO Pattern Examples Using the Factory Pattern Douglas C. Schmidt OO Pattern Examples Printing Subtrees Douglas C. Schmidt The Factory pattern is used by the Tree class to initialize Node subclasses: Tree::Tree int num : node_ new Int_Node num Tree::Tree const string &op, const Tree &t : node_ new Unary_Node op, t Tree::Tree const string &op, const Tree &t1, const Tree &t2 : node_ new Binary_Node op, t1, t2 Problem How do we print subtrees without revealing their types? Forces The Node subclass should be hidden within the Tree instances We don't want to become dependent on the use of Nodes, inheritance, & dynamic binding, etc. We don't want to expose dynamic memory management details to application developers Solution Use the Bridge pattern to shield the use of inheritance & dynamic binding Vanderbilt University 27 Vanderbilt University 26 OO Pattern Examples The Bridge Pattern Douglas C. Schmidt OO Pattern Examples Structure of the Bridge Pattern 1: method_impl() Douglas C. Schmidt Intent Decouple an abstraction from its implementation so that the two can vary independently This pattern resolves the following forces that arise when building extensible software with C++ 1. How to provide a stable, uniform interface that is both closed & open, i.e., interface is closed to prevent direct code changes Implementation is open to allow extensibility 2. How to manage dynamic memory more transparently & robustly 3. How to simplify the implementation of operator Vanderbilt University 28 Abstraction method() Implementor method_impl() Concrete ImplementorA method_impl() Concrete ImplementorB method_impl() Vanderbilt University 29 OO Pattern Examples Using the Bridge Pattern 1: print() Douglas C. Schmidt OO Pattern Examples Illustrating the Bridge Pattern in C++ Douglas C. Schmidt Tree print() Node print() The Bridge pattern is used for printing expression trees: void Tree::print std::ostream &os const this- node_- print os; Int Node Ternary print() Binary Node Node Unary print() print() Node print() Note how this pattern decouples the Tree interface for printing from the Node subclass implementation i.e., the Tree interface is xed, whereas the Node implementation varies However, clients need not be concerned about the variation . . . Vanderbilt University 30 Vanderbilt University 31 OO Pattern Examples Integrating with C++ I O Streams Douglas C. Schmidt OO Pattern Examples The Adapter Pattern Douglas C. Schmidt Problem Our Tree interface uses a print method, but most C++ programmers expect to use I O Streams Forces Want to integrate our existing C++ Tree class into the I O Stream paradigm without modifying our class or C++ I O Solution Use the Adapter pattern to integrate Tree with I O Streams Intent Convert the interface of a class into another interface client expects Adapter lets classes work together that couldn't otherwise because of incompatible interfaces This pattern resolves the following force: 1. How to transparently integrate the Tree with the C++ istd::ostream operators Vanderbilt University 32 Vanderbilt University 33 OO Pattern Examples Structure of the Adapter Pattern 1: request () Douglas C. Schmidt OO Pattern Examples Using the Adapter Pattern 1: operator<< Douglas C. Schmidt client Target request() client Target operator<< Adapter request() Adaptee 2: specific_request() specific_request() 34 iostream operator<< 2: print() Tree print() Vanderbilt University Vanderbilt University 35 OO Pattern Examples Using the Adapter Pattern Reference counting via the counted body" idiom Tree::Tree const Tree &t: node_ t.node_ ++this- node_- use_; Sharing, ref-counting. Douglas C. Schmidt OO Pattern Examples C++ Tree Implementation Douglas C. Schmidt The Adapter pattern is used to integrate with C++ I O Streams std::ostream &operator std::ostream &s, const Tree &tree tree.print s; This triggers Node * virtual call via tree.node_- print s, which is implemented as the following: *tree.node_- vptr 1 tree.node_, s; return s; void Tree::operator= const Tree &t if this == &t return; order important here! ++t.node_- use_; --this- node_- use_; if this- node_- use_ == 0 delete this- node_; this- node_ = t.node_; Note how the C++ code shown above uses I O streams to adapt" the Tree interface . . . 36 Vanderbilt University Vanderbilt University 37 OO Pattern Examples C++ Tree Implementation cont'd Douglas C. Schmidt OO Pattern Examples Tree::~Tree Ref-counting, garbage collection --this- node_- use_; if this- node_- use_ = 0 delete this- node_; include istd::ostream.h include "Tree.h" C++ Main Program Douglas C. Schmidt int main int, char * const Tree t1 = Tree "*", Tree "-", 5, Tree "+", 3, 4; cout t1 endl; prints -5 * 3 + 4 const Tree t2 = Tree "*", t1, t1; prints -5 * 3 + 4 * -5 * 3 + 4. cout t2 endl; return 0; Destructors of t1 & t2 recursively delete entire tree when leaving scope. Vanderbilt University 38 Vanderbilt University 39 Do Binary Node Unary Node Int Node Do Binary Node Unary Node Expression Tree Diagram 1 Expression tree for t1 = -5 * 3 + 4 Expression Tree Diagram 2 Int Node 4 4 OO Pattern Examples OO Pattern Examples Vanderbilt University Expression tree for t2 = t1 * t1 print( ) print( ) + + 3 t2 * t1 * t1 * 5 3 OO Pattern Examples Adding Ternary Nodes Douglas C. Schmidt OO Pattern Examples Extending the existing program to support ternary nodes is straightforward i.e., just derive new class Ternary Node to handle ternary operators, e.g., a == b ? c : d, etc. include "Node.h" class Ternary_Node : public Node public: Ternary_Node const string &, const Tree &, const Tree &, const Tree &; virtual void print std::ostream & const; private: const string operation_; Tree left_, middle_, right_; ; include "Ternary_Node.h" Ternary_Node::Ternary_Node const string &op, const Tree &a, const Tree &b, const Tree &c : operation_ op, left_ a, middle_ b, right_ c C++ Ternary Node Implementation Douglas C. Schmidt void Ternary_Node::print std::ostream &stream const stream this- operation_ "" this- left_ recursive call "," this- middle_ recursive call "," this- right_ recursive call ""; Vanderbilt University 42 Vanderbilt University Vanderbilt University 5 - - 43 OO Pattern Examples C++ Ternary Node Implementation cont'd struct Tree_Node enum NUM, UNARY, BINARY, TERNARY tag_; same as before union same as before. But, add this: struct Tree_Node *l_, *m_, *r_; ternary_; c; define ternary_ c.ternary_ ; Douglas C. Schmidt OO Pattern Examples Modified class Tree Factory class Tree add 1 class constructor public: Tree const string &, const Tree &, const Tree &, const Tree & : node_ new Ternary_Node op, l, m, r Same as before . . . On the other hand, modifying the original algorithmic approach requires changing 1 the original data structures, e.g., Di erences from Algorithmic Implementation Douglas C. Schmidt Vanderbilt University 44 Vanderbilt University 45 OO Pattern Examples Di erences from Algorithmic Implementation cont'd Douglas C. Schmidt OO Pattern Examples Summary of Expression Tree Example Douglas C. Schmidt & 2 many parts of the code, e.g., void print_tree Tree_Node *root same as before case TERNARY: must be TERNARY. printf ""; print_tree root- ternary_.l_; printf "c", root- op_ 0 ; print_tree root- ternary_.m_; printf "c", root- op_ 1 ; print_tree root- ternary_.r_; printf ""; break; same as before OO version represents a more complete modeling of the application domain e.g., splits data structures into modules that correspond to objects" & relations in expression trees Use of C++ language features simpli es the design and facilitates extensibility e.g., implementation follows directly from design Use of patterns helps to motivate, justify, & generalize design choices Vanderbilt University 46 Vanderbilt University 47 OO Pattern Examples Potential Problems with OO Design Douglas C. Schmidt OO Pattern Examples Case Study: System Sort Douglas C. Schmidt Solution is very data structure rich" e.g., requires con guration management to handle many headers & .cpp les! May be somewhat less e cient than original algorithmic approach e.g., due to virtual function overhead In general, however, virtual functions may be no less ine cient than large switch statements or if else chains . . . As a rule, be careful of micro vs. macro optimizations i.e., always pro le your code! 48 Vanderbilt University Develop a general-purpose system sort It sorts lines of text from standard input and writes the result to standard output e.g., the UNIX system sort In the following, we'll examine the primary forces that shape the design of this application For each force, we'll examine patterns that resolve it Vanderbilt University 49 OO Pattern Examples External Behavior of System Sort Douglas C. Schmidt OO Pattern Examples High-level Forces Douglas C. Schmidt A line" is a sequence of characters terminated by a newline Default ordering is lexicographic by bytes in machine collating sequence e.g., ASCII The ordering is a ected globally by the following options: Ignore case -f Sort numerically -n Sort in reverse -r Begin sorting at a speci ed eld -k Begin sorting at a speci ed column -c Your program need not sort les larger than main memory 50 Solution should be both time & space e cient e.g., must use appropriate algorithms and data structures E cient I O & memory management are particularly important Our solution uses minimal dynamic binding to avoid unnecessary overhead Solution should leverage reusable components e.g., istd::ostreams, Array & Stack classes, etc. Solution should yield reusable components e.g., e cient input classes, generic sort routines, etc. Vanderbilt University Vanderbilt University 51 OO Pattern Examples Top-level Algorithmic View of the Solution Douglas C. Schmidt OO Pattern Examples Top-level Algorithmic View of the Solution cont'd Douglas C. Schmidt Note the use of existing C++ mechanisms like I O streams Reusable function: template typename ARRAY void sort ARRAY &a; int main int argc, char *argv parse_args argc, argv; Input input; cin input; sort input; cout input; Avoid the grand mistake of using top-level algorithmic view to structure the design . . . Structure the design to resolve the forces! Don't focus on algorithms or data, but instead look at the problem, its participants, & their interactions! Vanderbilt University 52 Vanderbilt University 53 OO Pattern Examples General OOD Solution Approach Douglas C. Schmidt OO Pattern Examples C++ Class Model System Sort Sort_AT Adapter Douglas C. Schmidt Identify the classes in the application problem space & solution space e.g., stack, array, input class, options, access table, sorts, etc. Recognize & apply common design patterns e.g., Singleton, Factory, Adapter, Iterator Implement a framework to coordinate components e.g., use C++ classes & parameterized types Options GLOBAL STRATEGIC COMPONENTS Sort Line_Ptrs Sort_AT Adapter ARRAY Sort TACTICAL COMPONENTS TYPE Access Table Input TYPE TYPE Stack Array Vanderbilt University 54 Vanderbilt University 55 OO Pattern Examples C++ Class Components Strategic components System Sort Facade that integrates everything . . . Sort AT Adapter Integrates Array & Access Table Options Manages globally visible options Sort e.g., both quicksort & insertion sort Douglas C. Schmidt OO Pattern Examples C++ Class Components Douglas C. Schmidt Tactical components Stack Used by non-recursive quick sort Array Stores sorts pointers to lines & elds Access Table Used to store input Input E ciently reads arbitrary sized input using only 1 dynamic allocation & 1 copy Vanderbilt University 56 Vanderbilt University 57 OO Pattern Examples Detailed Format for Solution Douglas C. Schmidt OO Pattern Examples Reading Input E ciently Douglas C. Schmidt Note the separation of concerns Prototypes template typename ARRAY void sort ARRAY &a; void operator std::istream &, Sort_AT_Adapter &; void operator std::ostream &, const Sort_AT_Adapter &; int main int argc, char *argv Options::instance - parse_args argc, argv; cin System_Sort::instance - access_table ; sort System_Sort::instance - access_table ; cout System_Sort::instance - access_table ; Problem The input to the system sort can be arbitrarily large e.g., up to 1 2 size of main memory Forces To improve performance solution must minimize: 1. Data copying & data manipulation 2. Dynamic memory allocation Solution Create an Input class that reads arbitrary input e ciently Vanderbilt University 58 Vanderbilt University 59 OO Pattern Examples Access Table Format ACCESS BUFFER Douglas C. Schmidt OO Pattern Examples E ciently reads arbitrary-sized input using only 1 dynamic allocation class Input public: Reads from input up to terminator , replacing search with replace . Returns dynamically allocated buffer. char *read std::istream &input, int terminator = EOF, int search = ' n', int replace = ' 0'; Number of bytes replaced. size_t replaced const; Size of buffer. size_t size const; private: Recursive helper method. char *recursive_read ; . . . ; The Input Class Douglas C. Schmidt ACCESS ARRAY Vanderbilt University 60 Vanderbilt University 61 OO Pattern Examples char *Input::read std::istream &i, int t, int s, int r Initialize all the data members... return recursive_read ; char *Input::recursive_read char buffer BUFSIZ ; 1. Read input one character at a time, performing search replace until EOF is reached or buffer is full. 1.a If buffer is full, invoke recursive_read recursively. 1.b If EOF is reached, dynamically allocate chunk large enough to hold entire input 2. On way out of recursion, copy buffer into chunk The Input Class cont'd Douglas C. Schmidt OO Pattern Examples Design Patterns in the System Sort Douglas C. Schmidt Facade Provide a uni ed interface to a set of interfaces in a subsystem Facade de nes a higher-level interface that makes the subsystem easier to use e.g., sort function provides a facade for the complex internal details of e cient sorting Adapter Convert the interface of a class into another interface clients expect Adapter lets classes work together that couldn't otherwise because of incompatible interfaces e.g., make Access Table conform to interfaces expected by sort & istd::ostreams 62 Vanderbilt University 63 Vanderbilt University OO Pattern Examples Design Patterns in System Sort cont'd Douglas C. Schmidt OO Pattern Examples Design Patterns in System Sort cont'd Douglas C. Schmidt Factory Centralize assembly of resources needed to create objects e.g., decouple initialization of Line Ptrs used by Access Table from their subsequent use Bridge Decouple an abstraction from its implementation so that the two can vary independently e.g., comparing two lines to determine ordering Strategy De ne a family of algorithms, encapsulate each one, & make them interchangeable e.g., allow exible pivot selection 64 Vanderbilt University Singleton Ensure a class has only one instance, & provide a global point of access to it e.g., provides a single point of access for the system sort facade & for program options Iterator Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation e.g., provides a way to print out the sorted lines without exposing representation or initialization Vanderbilt University 65 OO Pattern Examples Sort Algorithm Douglas C. Schmidt OO Pattern Examples Quicksort Optimizations 1. Non-recursive Uses an explicit stack to reduce function call overhead 2. Median of 3 pivot selection Reduces probability of worse-case time complexity 3. Guaranteed log n space complexity Always pushes" larger partition 4. Insertion sort for small partitions Insertion sort runs fast on almost sorted data Douglas C. Schmidt For e ciency, two types of sorting algorithms are used: 1. Quicksort Highly time & space e cient sorting arbitrary data On log n average-case time complexity On2 worst-case time complexity Olog n space complexity Optimizations are used to avoid worst-case behavior 2. Insertion sort Highly time & space e cient for sorting almost ordered" data On2 average- & worst-case time complexity O1 space complexity Vanderbilt University 66 Vanderbilt University 67 OO Pattern Examples Selecting a Pivot Value Douglas C. Schmidt OO Pattern Examples The Strategy Pattern Douglas C. Schmidt Problem There are various algorithms for selecting a pivot value e.g., randomization, median of three, etc. Forces Di erent input may sort more e ciently using di erent pivot selection algorithms Solution Use the Strategy pattern to select the pivot selection algorithm Intent De ne a family of algorithms, encapsulate each one, & make them interchangeable Strategy lets the algorithm vary independently from clients that use it This pattern resolves the following forces 1. How to extend the policies for selecting a pivot value without modifying the main quicksort algorithm 2. Provide a one size ts all interface without forcing a one size ts all implementation Vanderbilt University 68 Vanderbilt University 69 OO Pattern Examples Structure of the Strategy Pattern STRATEGY Douglas C. Schmidt OO Pattern Examples Using the Strategy Pattern Pvot i Strategy get_pivot() Douglas C. Schmidt Context context_interface() Strategy algorithm_interface() quick_sort Concrete Strategy A algorithm_interface() Concrete Strategy C algorithm_interface() pivot_strat->get_pivot (array, lo, hi) Concrete Strategy B algorithm_interface() Select First 70 Vanderbilt University Random Median of Three Vanderbilt University 71 OO Pattern Examples Implementing the Strategy Pattern template typename ARRAY, class PIVOT_STRAT quick_sort ARRAY &array, PIVOT_STRAT *pivot_strat for ;; typename ARRAY::TYPE pivot = Note 'lo' & 'hi' should be passed by reference so get_pivot can reorder the values & update 'lo' & 'hi' accordingly... pivot_strat- get_pivot array, lo, hi; Partition array lo, hi relative to pivot . . . Douglas C. Schmidt OO Pattern Examples Implementing the Strategy Pattern Douglas C. Schmidt ARRAY is the particular context" template typename ARRAY void sort ARRAY &array Pivot_Strategy ARRAY *pivot_strat = Pivot_Factory ARRAY ::make_pivot Options::instance - pivot_strat ; std::auto_ptr Pivot_Strategy ARRAY holder pivot_strat; Ensure exception safety. ARRAY temp = array; quick_sort temp, pivot_strat; Destructor of holder deletes array = temp; pivot_strat . Vanderbilt University 72 Vanderbilt University 73 OO Pattern Examples De nes a xed size stack for use with non-recursive quicksort Fixed-size Stack Douglas C. Schmidt OO Pattern Examples Devising a Simple Sort Interface Douglas C. Schmidt template typename T, size_t SIZE class Fixed_Stack public: bool push const T &new_item; bool pop T &item; bool is_empty ; . . . private: T stack_ SIZE ; size_t top_; ; Problem Although the implementation of the sort function is complex, the interface should be simple to use Key forces Complex interface are hard to use, error prone, and discourage extensibility & reuse Conceptually, sorting only makes a few assumptions about the array" it sorts e.g., supports operator methods, size, & trait TYPE We don't want to arbitrarily limit types of arrays we can sort Solution Use the Facade & Adapter patterns to simplify the sort program 74 Vanderbilt University 75 Vanderbilt University OO Pattern Examples Facade Pattern Douglas C. Schmidt OO Pattern Examples Structure of the Facade Pattern Facade Douglas C. Schmidt Intent Provide a uni ed interface to a set of interfaces in a subsystem Facade de nes a higher-level interface that makes the subsystem easier to use This pattern resolves the following forces: 1. Simpli es the sort interface e.g., only need to support operator & size methods, & element 2. Allows the implementation to be e cient and arbitrarily complex without a ecting clients TYPE EXTERNALLY VISIBLE HIDDEN Vanderbilt University 76 Vanderbilt University 77 OO Pattern Examples Using the Facade Pattern ARRAY Douglas C. Schmidt OO Pattern Examples Centralizing Option Processing Douglas C. Schmidt EXTERNALLY VISIBLE HIDDEN Sort TYPE Quick Sort ARRAY Stack ARRAY Insert Sort Vanderbilt University 78 Problem Command-line options must be global to many parts of the sort program Key forces Unrestricted use of global variables increases system coupling & can violate encapsulation Initialization of static objects in C++ can be problematic Solution Use the Singleton pattern to centralize option processing Vanderbilt University 79 OO Pattern Examples Singleton Pattern Douglas C. Schmidt OO Pattern Examples Structure of the Singleton Pattern Douglas C. Schmidt Intent Ensure a class has only one instance, & provide a global point of access to it This pattern resolves the following forces: 1. Localizes the creation & use of global" variables to well-de ned objects 2. Preserves encapsulation 3. Ensures initialization is done after program has started & only on rst use 4. Allow transparent subclassing of Singleton implementation if (unique_instance_ == 0) unique_instance_ = new Singleton; return unique_instance_; static instance() singleton_operation() get_singleton_data() static unique_instance_ singleton_data_ Vanderbilt University 81 Singleton Vanderbilt University 80 OO Pattern Examples Using the Singleton Pattern Douglas C. Schmidt OO Pattern Examples Options Class Douglas C. Schmidt if (unique_instance_ == 0) unique_instance_ = new Options; return unique_instance_; This manages globally visible options class Options public: static Options *instance ; bool parse_args int argc, char *argv Options static instance() bool enabled() field_offset() static unique_instance_ options_ Vanderbilt University 82 ; These options are stored in octal order so that we can use them as bitmasks! enum Option FOLD = 01, NUMERIC = 02, REVERSE = 04, NORMAL = 010 ; enum Pivot_Strategy MEDIAN, RANDOM, FIRST ; Vanderbilt University 83 OO Pattern Examples Options Class cont'd define SET_BITWORD, OPTION WORD |= OPTION define CLR_BITWORD, OPTION WORD &= ~OPTION Douglas C. Schmidt OO Pattern Examples Options Class cont'd Douglas C. Schmidt bool enabled Option o; int field_offset ; Offset from BOL. Pivot_Strategy pivot_strat ; int *compare const char *l, const char *r; protected: Options ; Ensure Singleton. u_long options_; Maintains options bitmask . . . int field_offset_; static Options *instance_; Singleton. . . . bool Options::parse_args int argc, char *argv for int c; c = getopt argc, argv, ``nrfs:k:c:t:'' != EOF; switch c case 'n': CLR_BIT options_, Options::FOLD; CLR_BIT options_, Options::NORMAL; SET_BIT options_, Options::NUMERIC; break; ; Vanderbilt University 84 Vanderbilt University 85 OO Pattern Examples One way to implement sort comparison operator: Using the Options Class Douglas C. Schmidt OO Pattern Examples Simplifying Comparisons Douglas C. Schmidt int Line_Ptrs::operator const Line_Ptrs &rhs const Options *options = Options::instance ; 0; if options- enabled Options::NORMAL return strcmp this- bof_, rhs.bof_ else if options- enabled Options::NUMERIC; return numcmp this- bof_, rhs.bof_ 0; else if options- enabled Options::FOLD return strcasecmp this- bof_, rhs.bof_ 0; Problem The comparison operator shown above is somewhat complex Forces It's better to determine the type of comparison operation during the initialization phase But the interface shouldn't change Solution Use the Bridge pattern to separate interface from implementation We'll see another approach later on using Bridge 86 Vanderbilt University 87 Vanderbilt University OO Pattern Examples The Bridge Pattern Douglas C. Schmidt OO Pattern Examples Structure of the Bridge Pattern 1: method_impl() Douglas C. Schmidt Intent Decouple an abstraction from its implementation so that the two can vary independently This pattern resolves the following forces that arise when building extensible software 1. How to provide a stable, uniform interface that is both closed & open, i.e., Closed to prevent direct code changes Open to allow extensibility 2. How to simplify the Line_Ptrs::operator implementation & reference counting for Access Table bu er Vanderbilt University 88 Abstraction method() Implementor method_impl() Concrete ImplementorA method_impl() Concrete ImplementorB method_impl() Vanderbilt University 89 OO Pattern Examples Using the Bridge Pattern 1: compare() Douglas C. Schmidt OO Pattern Examples Using the Bridge Pattern Douglas C. Schmidt The following is the comparison operator used by sort Line_Ptrs operator< Options compare() int Line_Ptrs::operator const Line_Ptrs &rhs const return *Options::instance - compare bof_, rhs.bof_ 0; strcmp() This solution is much more concise However, there's an extra level of function call indirection . . . Which is equivalent to a virtual function call numcmp() strcasecmp() Vanderbilt University 90 Vanderbilt University 91 OO Pattern Examples Initializing the Comparison Operator Douglas C. Schmidt OO Pattern Examples The Adapter Pattern Douglas C. Schmidt Problem How does the compare pointer-to-method get assigned? int *compare const char *left, const char *right; Forces There are many di erent choices for compare, depending on which options are enabled We only want to worry about initialization details in one place Initialization details may change over time We'd like to do as much work up front to reduce overhead later on Solution Use a Factory pattern to initialize the comparison operator Vanderbilt University 92 Intent Convert the interface of a class into another interface clients expect Adapter lets classes work together that couldn't otherwise because of incompatible interfaces This pattern resolves the following forces: 1. How to transparently integrate the Access Table with the sort routine 2. How to transparently integrate the Access Table with the C++ istd::ostream operators Vanderbilt University 93 OO Pattern Examples Structure of the Adapter Pattern Target request() Douglas C. Schmidt OO Pattern Examples Using the Adapter Pattern "conforms to" Douglas C. Schmidt 1: request () ARRAY client sort 1: ARRAY::TYPE t = array[i] ARRAY ARRAY::TYPE ARRAY::TYPE operator size() Adapter request() 2: specific_request() Adaptee specific_request() "conforms to" Line_Ptrs Sort_AT_Adapter typedef Line_Ptrs TYPE make_table() operator size() make_table() length() element() TYPE Access_Table Vanderbilt University 94 Vanderbilt University 95 OO Pattern Examples Dynamic Array Table template typename T class Access_Table public: Factory Method for initializing Access_Table. virtual int make_table size_t lines, char *buffer = 0; Release buffer memory. virtual ~Access_Table ; T &element size_t index; Reference to indexth element. size_t length const; Length of the access_array. Array T &array void const; Return reference to array. protected: Array T access_array_; Access table is array of T. Access_Table_Impl *access_table_impl_; Ref counted buffer. ; Douglas C. Schmidt OO Pattern Examples The Access Table Class Douglas C. Schmidt De nes a variable-sized array for use by the Access E ciently maps indices onto elements in the data bu er template typename T class Array public: Array size_t size = 0; int init size_t size; T &operator size_t index; size_t size const; T *begin const; STL iterator methods. T *end const; . . . private: T *array_; size_t size_; ; Vanderbilt University 96 Vanderbilt University 97 OO Pattern Examples The Access Table Impl Class Douglas C. Schmidt OO Pattern Examples The Sort AT Adapter Class sort Douglas C. Schmidt class Access_Table_Impl Part of the Bridge pattern public: Access_Table_Impl void; Default constructor Access_Table_Impl char *buffer; Constructor Virtual destructor ensures subclasses are virtual virtual ~Access_Table_Impl void; Adapts the Access Table to conform to the ARRAY interface expected by struct Line_Ptrs Comparison operator used by sort. int operator const Line_Ptrs & const; Beginning of line & field column. char *bol_, *bof_; ; void void char void add_ref void; Increment reference count remove_ref void; Decrement reference count *get_buffervoid; Get buffer from the class set_bufferchar *; Set buffer private: char *buffer_; Underlying buffer size_t ref_count_; Refcount tracks deletion. ; Vanderbilt University 98 Vanderbilt University 99 OO Pattern Examples The Sort AT Adapter Class Douglas C. Schmidt OO Pattern Examples The Factory Pattern Douglas C. Schmidt class Sort_AT_Adapter : Note class form of the Adapter private Access_Table Line_Ptrs public: virtual int make_table size_t num_lines, char *buffer; typedef Line_Ptrs TYPE; Type trait. These methods adapt Access_Table methods . . . Line_Ptrs &operator size_t index; size_t size const; ; Put these into separate file. Line_Ptrs &Sort_AT_Adapter::operator return element i; size_t Sort_AT_Adapter::size const Intent Centralize the assembly of resources necessary to create an object Decouple object creation from object use by localizing creation knowledge This pattern resolves the following forces: Decouple initialization of the compare operator from its subsequent use Makes it easier to change comparison policies later on e.g., adding new command-line options size_t i return length ; Vanderbilt University 100 Vanderbilt University 101 OO Pattern Examples Structure of the Factory Pattern Douglas C. Schmidt OO Pattern Examples Using the Factory Pattern for Comparisons Douglas C. Schmidt Factory make_product() creates Product product = ... return product creates Options parse_args() initialize compare Product Vanderbilt University 102 Compare Function Vanderbilt University 103 OO Pattern Examples Code for Using the Factory Pattern Code for Using the Factory Pattern cont'd Douglas C. Schmidt OO Pattern Examples Douglas C. Schmidt The following initialization is done after command-line options are parsed int numcmp const char *s1, const char * s2 double d1 = strtod s1, 0, d2 = strtod s2, 0; if d1 d2 return -1; else if d1 d2 return 1; else if d1 == d2 return 0; bool Options::parse_args int argc, char *argv We need to write a numcmp adapter function to conform to the API used by the compare pointer-to-function . . . if this- enabled Options::NORMAL this- compare = &strcmp; else if this- enabled Options::NUMERIC this- compare = &numcmp; else if this- enabled Options::FOLD this- compare = &strcasecmp; . . . Vanderbilt University 104 Vanderbilt University 105 OO Pattern Examples Initializing the Access Table Douglas C. Schmidt OO Pattern Examples Factory Method Pattern Douglas C. Schmidt Problem One of the nastiest parts of the whole system sort program is initializing the Access Table Key forces We don't want initialization details to a ect subsequent processing Makes it easier to change initialization policies later on e.g., using the Access Table in non-sort applications Solution Use the Factory Method pattern to initialize the Access Table Intent De ne an interface for creating an object, but let subclasses decide which class to instantiate Factory Method lets a class defer instantiation to subclasses This pattern resolves the following forces: Decouple initialization of the Access Table from its subsequent use Improves subsequent performance by pre-caching beginning of each eld & line Makes it easier to change initialization policies later on e.g., adding new command-line options Vanderbilt University 106 Vanderbilt University 107 OO Pattern Examples Structure of the Factory Method Pattern Creator factory_method() = 0 make_product() Douglas C. Schmidt OO Pattern Examples Using the Factory Method Pattern for Access Table Initialization Access Table make_table() = 0 TYPE Douglas C. Schmidt Product Product *product = factory_method() return product Concrete Creator factory_method() Sort AT Adapter make_table() Line Ptrs Concrete Product Vanderbilt University CREATES return new Concrete_Product // initialize the table 108 Vanderbilt University 109 OO Pattern Examples Using the Factory Method Pattern for the Sort AT Adapter Douglas C. Schmidt OO Pattern Examples Implementing the Factory Method Pattern Douglas C. Schmidt The following istd::ostream Adapter initializes the access table void operator Input input; Read entire stdin into buffer. char *buffer = input.read is; size_t num_lines = input.replaced ; Factory Method initializes Access_Table at.make_table num_lines, buffer; Sort AT Adapter The Access Table Factory class has a Factory Method that initializes Sort AT Adapter Factory Method initializes Access_Table. int Sort_AT_Adapter::make_table size_t num_lines, char *buffer Array assignment op. this- access_array_.resize num_lines; this- buffer_ = buffer; Obtain ownership. std::istream &is, Sort_AT_Adapter &at . size_t count = 0; Vanderbilt University 110 Vanderbilt University 111 OO Pattern Examples Implementing the Factory Method Pattern cont'd Douglas C. Schmidt OO Pattern Examples Initializing the Access Table with Input Bu er Douglas C. Schmidt Iterate through the buffer & determine where the beginning of lines & fields must go. for Line_Ptrs_Iter iter buffer, num_lines; iter.is_done == 0; iter.next Line_Ptrs line_ptr = iter.current_element ; this- access_array_ count++ = line_ptr; Problem We'd like to initialize the Access Table without having to know the input bu er is represented Key force Representation details can often be decoupled from accessing each item in a container or collection Solution Use the Iterator pattern to scan through the bu er Vanderbilt University 112 Vanderbilt University 113 OO Pattern Examples Iterator Pattern Douglas C. Schmidt OO Pattern Examples The Iterator pattern provides a way to initialize the Access Table without knowing how the bu er is represented Line_Ptrs_Iter::Line_Ptrs_Iter char *buffer, size_t num_lines; Line_Ptrs Line_Ptrs_Iter::current_element Line_Ptrs lp; Determine beginning of next line lp.bol_ = . . . lp.bof_ = . . . return lp; & next field . . . Intent Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation The C++ Standard Library STL is heavily based on the iterator pattern, e.g., Iterator Pattern cont'd Douglas C. Schmidt int main int argc, char *argv std::vector std::string args; for int i = 1; i argc; ++i args.push_back std::string argv i ; for std::vector std::string ::iterator j = args.begin ; j != args.end ; ++j cout *j_ endl; Vanderbilt University 114 Vanderbilt University 115 OO Pattern Examples Iterator Pattern cont'd Douglas C. Schmidt OO Pattern Examples Summary of System Sort Case Study Douglas C. Schmidt Iterator provides a way to print out sorted lines void operator std::ostream &os, const Line_Ptrs lp os lp.bol_; void operator std::ostream &os, const Sort_AT_Adapter &at if Options::instance - enabled Options::REVERSE std::reverse_copy at.array .begin , at.array .end , std::::ostream_iterator System_Sort::Line_Ptrs os, " n"; else std::copy at.array .begin , at.array .end , std::::ostream_iterator System_Sort::Line_Ptrs os, " n"; This case study illustrates using OO techniques to structure a modular, reusable, & highly e cient system Design patterns help to resolve many key forces Performance of our system sort is comparable to existing UNIX system sort Use of C++ features like parameterized types and inlining minimizes penalty from increased modularity, abstraction, & extensibility Vanderbilt University 116 Vanderbilt University 117 OO Pattern Examples Case Study: Sort Veri er Douglas C. Schmidt OO Pattern Examples General Form of Solution The following is a general use-case for this routine: template typename ARRAY void sort ARRAY &a; template typename ARRAY int check_sort const ARRAY &o, const ARRAY &p; int main int argc, char *argv Options::instance - parse_args argc, argv; Input original; Input potentially_sorted; Douglas C. Schmidt Verify whether a sort routine works correctly i.e., output of the sort routine must be an ordered permutation of the original input This is useful for checking our system sort routine! The solution is harder than it looks at rst glance . . . As before, we'll examine the key forces & discuss design patterns that resolve the forces Vanderbilt University 118 Vanderbilt University 119 OO Pattern Examples unsorted 0 8 4 4 7 8 13 13 15 18 13 18 15 4 13 4 7 sorted, but not permuted permuted, but not sorted sorted and permuted 0 0 0 0 0 0 0 General Form of Solution cont'd 7 13 4 15 18 13 8 4 Douglas C. Schmidt OO Pattern Examples Common Problems Douglas C. Schmidt cin input; std::copy original.begin , original.end , potentially_sorted.begin ; sort potentially_sorted; if check_sort original, potentially_sorted == -1 cerr "sort failed" endl; else cout "sort worked" endl; Several common problems: Sort routine may zero out data though it will appear sorted . . . ;- Sort routine may fail to sort data Sort routine may erroneously add new values Vanderbilt University 120 Vanderbilt University 121 OO Pattern Examples Forces Douglas C. Schmidt OO Pattern Examples Forces cont'd Douglas C. Schmidt Solution should be both time & space e cient e.g., it should not take more time to check than to sort in the rst place! Also, this routine may be run many times consecutively, which may facilitate certain space optimizations We cannot assume the existence of a correct" sorting algorithm . . . Therefore, to improve the chance that our solution is correct, it must be simpler than writing a correct sorting routine Quis costodiet ipsos custodes? Who shall guard the guardians? Multiple implementations will be necessary, depending on properties of the data being examined, e.g., 1. if data values are small in relation to number of items & integrals use . . . 2. if data has no duplicate values use . . . 3. if data has duplicate values use . . . This problem illustrates a simple example of program families" i.e., we want to reuse as much code and or design across multiple solutions as possible Vanderbilt University 122 Vanderbilt University 123 OO Pattern Examples Strategies Douglas C. Schmidt OO Pattern Examples General OOD Solution Approach Douglas C. Schmidt Implementations of search structure vary according to data, e.g., 1. Range Vector ON time complexity & space e cient for sorting small" ranges of integral values 2. Binary Search version 1 On log n time complexity & space e cient but does not handle duplicates 3. Binary Search version 2 On log n time complexity, but handles duplicates 4. Hashing On best average case, but On2 worst case, handles duplicates, but potentially not as space e cient 124 Vanderbilt University Identify the objects" in the application & solution space e.g., use a search structure ADT organization with member function such as insert & remove Recognize common design patterns e.g., Strategy & Factory Method Implement a framework to coordinate multiple implementations e.g., use classes, parameterized types, inheritance & dynamic binding Vanderbilt University 125 OO Pattern Examples General OOD solution approach cont'd Douglas C. Schmidt OO Pattern Examples High-level Algorithm e.g., pseudo code template typename ARRAY int check_sort const ARRAY &original, const ARRAY &potential_sort Perform basic sanity check to see if the potential_sort is actually in order can also detect duplicates here Douglas C. Schmidt C++ framework should be amenable to: Extension & Contraction May discover better implementations May need to conform to resource constraints May need to work on multiple types of data Performance Enhancement May discover better ways to allocate & cache memory Note, improvements should be transparent to existing code . . . Portability May need to run on multiple platforms Vanderbilt University 126 Vanderbilt University 127 OO Pattern Examples High-level Algorithm cont'd Douglas C. Schmidt OO Pattern Examples UML Class Diagram for C++ Solution TYPE Douglas C. Schmidt if basic sanity check succeeds then Initialize search structure, srchstrct for i 0 to size - 1 loop insert potential_sort i into srchstrct for i 0 to size - 1 loop if remove original i from srchstrct fails then return ERROR return SUCCESS else return ERROR end if Search Struct LONG TYPE Range Vector TYPE Hash Table Binary Search Nodups TYPE Binary Search Dups 129 Vanderbilt University 128 Vanderbilt University OO Pattern Examples C++ Class Interfaces Douglas C. Schmidt OO Pattern Examples C++ Class interfaces cont'd Douglas C. Schmidt Search structure base class. template typename T class Search_Strategy public: virtual bool insert const T &new_item = 0; virtual bool remove const T &existing_item = 0; virtual ~Search_Strategy = 0; ; Strategy Factory class template typename ARRAY Search_Struct public: Singleton method. static Search_Struct ARRAY *instance ; Factory Method virtual Search_Strategy typename ARRAY::TYPE make_strategy const ARRAY &; ; * Vanderbilt University 130 Vanderbilt University 131 OO Pattern Examples C++ Class interfaces cont'd Douglas C. Schmidt OO Pattern Examples C++ Class interfaces cont'd Douglas C. Schmidt Strategy subclasses Note the template specialization class Range_Vector : public Search_Strategy long typedef long TYPE; * . . . * ; ; template typename ARRAY class Binary_Search_Nodups : public Search_Strategy typename ARRAY::TYPE typedef typename ARRAY::TYPE TYPE; ; * . . . * template typename ARRAY class Binary_Search_Dups : public Search_Strategy typename ARRAY::TYPE typedef typename ARRAY::TYPE TYPE; * . . . * template typename T class Hash_Table : public Search_Strategy T typedef typename ARRAY::TYPE TYPE; ; * . . . * Vanderbilt University 132 Vanderbilt University 133 Using the Strategy Pattern Search Struct Strategy TYPE OO Pattern Examples Binary Search Dups Binary Search Nodups Factory Method De ne an interface for creating an object, but let subclasses decide which class to instantiate Factory Method lets a class defer instantiation to subclasses In addition, the Facade, Iterator, Singleton, & Strategy patterns are used This pattern extends the strategies for checking if an array is sorted without modifying the check sort algorithm TYPE TYPE TYPE OO Pattern Examples Design Patterns in Sort Veri er Douglas C. Schmidt Do Hash Table Vanderbilt University 134 Vanderbilt University check_sort long Range Vector OO Pattern Examples The Factory Method Pattern Douglas C. Schmidt OO Pattern Examples Structure of the Factory Method Pattern Creator factory_method() = 0 make_product() Douglas C. Schmidt Intent De ne an interface for creating an object, but let subclasses decide which class to instantiate Factory Method lets a class defer instantiation to subclasses This pattern resolves the following force: 1. How to extend the initialization strategy in the sort veri er transparently Product Product *product = factory_method() return product Concrete Creator factory_method() Concrete Product CREATES return new Concrete_Product Vanderbilt University 136 Vanderbilt University 137 OO Pattern Examples Using the Factory Method Pattern Search Strategy Douglas C. Schmidt OO Pattern Examples Implementing the check sort Function Douglas C. Schmidt e.g., C++ code for the sort veri cation strategy Search Struct make_strategy() New Search Strategy New Search Struct make_strategy() CREATES template typename ARRAY int check_sort const ARRAY &orig, const ARRAY &p_sort if orig.size != p_sort.size return -1; auto_ptr Search_Strategy typename ARRAY::TYPE ss = Search_Struct ARRAY ::instance - make_strategy p_sort; return new New_Search_Struct Vanderbilt University 138 Vanderbilt University 139 OO Pattern Examples Implementing the check sort Function cont'd Factory Method template typename ARRAY Search_Strategy typename ARRAY::TYPE Search_Struct ARRAY ::make_strategy const ARRAY &potential_sort int duplicates = 0; * Douglas C. Schmidt OO Pattern Examples Initializing the Search Structure Douglas C. Schmidt for int i = 0; i p_sort.size ; ++i if ss- insert p_sort i == false return -1; for int i = 0; i orig.size ; ++i if ss- remove orig i == false return -1; return 0; auto_ptr's destructor deletes the memory . . . for size_t i = 1; i potential_sort.size ; ++i if potential_sort i potential_sort i - 1 return 0; else if potential_sort i == potential_sort i - 1 ++duplicates; Vanderbilt University 140 Vanderbilt University 141 OO Pattern Examples Initializing the Search Structure cont'd Douglas C. Schmidt OO Pattern Examples Specializing the Search Structure for Range Vectors template Array long Search_Strategy long Search_Struct Array long ::make_strategy const Array long &potential_sort int duplicates = 0; * Douglas C. Schmidt if typeid potential_sort 0 == typeid long && range = size return new Range_Vector potential_sort 0 , potential_sort size - 1 else if duplicates == 0 return new Binary_Search_Nodups ARRAY potential_sort; else if size 2 return new Binary_Search_Dups ARRAY potential_sort, duplicates else return new Hash_Table typename ARRAY::TYPE size, &hash_function; for size_t i = 1; i size; ++i if potential_sort i potential_sort i - 1 return 0; else if potential_sort i == potential_sort i - 1 ++duplicates; long range = potential_sort size - 1 potential_sort 0 ; - Vanderbilt University 142 Vanderbilt University 143 OO Pattern Examples Specializing the Search Structure for Range Vectors Douglas C. Schmidt OO Pattern Examples Summary of Sort Veri er Case Study Douglas C. Schmidt if range = size return new Range_Vector potential_sort 0 , potential_sort size - 1 else if duplicates == 0 return new Binary_Search_Nodups long potential_sort; else if size 2 return new Binary_Search_Dups long potential_sort, duplicates else return new Hash_Table long size, &hash_function; The sort veri er illustrates how to use OO techniques to structure a modular, extensible, & e cient solution The main processing algorithm is simpli ed The complexity is pushed into the strategy objects & the strategy selection factory Adding new solutions does not a ect existing code The appropriate ADT search structure is selected at run-time based on the Strategy pattern Vanderbilt University 144 Vanderbilt University 145 ...
View Full Document

This note was uploaded on 02/27/2012 for the course CS 251 taught by Professor Staff during the Fall '08 term at Purdue.

Ask a homework question - tutors are online