// Purpose. Builder class Builder { public: // virtual void addFront( char ) = 0; // The monolithic design supports a virtual void addBack( char ) = 0; // single representation. The Builder virtual Array& getResult() = 0; // design allows a different rep per }; // Builder derived class, and the com- // mon input and parsing have been de- class BuilderOne : public Builder { // fined in the Director class. The D public: // constructs, the B returns result. void addFront( char ch ) { one.lst.push_back( ch ); } class Array { void addBack( char ch ) { public: one.lst.push_back( ch ); } void addFront( char ch ) { Array& getResult() { lst.push_front( ch ); } return one; } void addBack( char ch ) { private: lst.push_back( ch ); } OneEnded one; void traverse() { }; for (i=0; i < lst.size(); i++) cout << lst[i] << ' '; class BuilderTwo : public Builder { cout << endl; } public: private: void addFront( char ch ) { deque lst; int i; two.lst.push_front( ch ); } }; void addBack( char ch ) { two.lst.push_back( ch ); } string in[] = { "fa", "bb", "fc", Array& getResult() { "bd", "fe", "bf", "fg", "bh" }; return two; } private: void main( void ) { TwoEnded two; Array list; }; for (int i=0; i < 8; i++) if (in[i][0] == 'f') string in[] = { "fa", "bb", "fc", list.addFront( in[i][1] ); "bd", "fe", "bf", "fg", "bh" }; else if (in[i][0] == 'b') list.addBack( in[i][1] ); class Director { list.traverse(); } public: Director( Builder* b ) { // g e c a b d f h setBuilder( b ); } void setBuilder( Builder* b ) { ///////////////////\\\\\\\\\\\\\\\\\\\ bldr = b; } void construct() { class Array { public: for (int i=0; i < 8; i++) virtual void traverse() = 0; if (in[i][0] == 'f') }; bldr->addFront(in[i][1]); else if (in[i][0] == 'b') class OneEnded : public Array { bldr->addBack(in[i][1]); public: } friend class BuilderOne; private: void traverse() { Builder* bldr; for (i=0; i < lst.size(); i++) }; cout << lst[i] << ' '; cout << endl; } void main( void ) { private: BuilderOne one; vector lst; int i; BuilderTwo two; }; Director dir( &one ); class TwoEnded : public Array { dir.construct(); public: one.getResult().traverse(); friend class BuilderTwo; dir.setBuilder( &two ); void traverse() { dir.construct(); for (i=0; i < lst.size(); i++) two.getResult().traverse(); cout << lst[i] << ' '; } cout << endl; } private: // a b c d e f g h deque lst; int i; // g e c a b d f h }; // Purpose. Builder design pattern demo. // // Discussion. The forte of Builder is constructing a complex object step // by step. An abstract base class declares the standard construction // process, and concrete derived classes define the appropriate // implementation for each step of the process. In this example, // "distributed work packages" have been abstracted to be persistent and // platform independent. This means that the platform-specific mechanism // for implementing files, queues, and concurrency pathways is defined in // each platform's concrete derived class. A single "reader" object (i.e. // parser) retrieves the archived specification for a DistrWorkPackage and // proceeds to delegate each build step to the builder object that was // registered by the client. Upon completion, the client retrieves the // end result from the builder. #include #include #include enum PersistenceType { File, Queue, Pathway }; struct PersistenceAttribute { PersistenceType type; char value[30]; }; class DistrWorkPackage { public: DistrWorkPackage( char* type ) { sprintf( _desc, "Distributed Work Package for: %s", type); } void setFile ( char* f, char* v ) { sprintf( _temp, "\n File(%s): %s", f, v ); strcat( _desc, _temp); } void setQueue ( char* q, char* v ) { sprintf( _temp, "\n Queue(%s): %s", q, v ); strcat( _desc, _temp); } void setPathway( char* p, char* v ) { sprintf( _temp, "\n Pathway(%s): %s", p, v ); strcat(_desc,_temp); } const char* getState() { return _desc; } private: char _desc[200], _temp[80]; }; class Builder { public: virtual void configureFile( char* ) = 0; virtual void configureQueue( char* ) = 0; virtual void configurePathway( char* ) = 0; DistrWorkPackage* getResult() { return _result; } protected: DistrWorkPackage* _result; }; class UnixBuilder : public Builder { public: UnixBuilder() { _result = new DistrWorkPackage( "Unix" ); } void configureFile( char* name ) { _result->setFile( "flatFile", name ); } void configureQueue( char* queue ) { _result->setQueue( "FIFO", queue ); } void configurePathway( char* type ) { _result->setPathway( "thread", type ); } }; class VmsBuilder : public Builder { public: VmsBuilder() { _result = new DistrWorkPackage( "Vms" ); } void configureFile( char* name ) { _result->setFile( "ISAM", name ); } void configureQueue( char* queue ) { _result->setQueue( "priority", queue ); } void configurePathway( char* type ) { _result->setPathway( "LWP", type ); } }; class Reader { public: void setBuilder( Builder* b ) { _builder = b; } void construct( PersistenceAttribute[], int ); private: Builder* _builder; }; void Reader::construct( PersistenceAttribute list[], int num ) { for (int i=0; i < num; i++) if (list[i].type == File) _builder->configureFile( list[i].value ); else if (list[i].type == Queue) _builder->configureQueue( list[i].value ); else if (list[i].type == Pathway) _builder->configurePathway( list[i].value ); } const int NUM_ENTRIES = 6; PersistenceAttribute input[NUM_ENTRIES] = { {File, "state.dat"}, {File,"config.sys"}, {Queue, "compute"}, {Queue, "log"}, {Pathway, "authentication"}, {Pathway, "error processing"} }; void main() { UnixBuilder unixBuilder; VmsBuilder vmsBuilder; Reader reader; reader.setBuilder( &unixBuilder ); reader.construct( input, NUM_ENTRIES ); cout << unixBuilder.getResult()->getState() << endl; reader.setBuilder( &vmsBuilder ); reader.construct( input, NUM_ENTRIES ); cout << vmsBuilder.getResult()->getState() << endl; } // Distributed Work Package for: Unix // File(flatFile): state.dat // File(flatFile): config.sys // Queue(FIFO): compute // Queue(FIFO): log // Pathway(thread): authentication // Pathway(thread): error processing // Distributed Work Package for: Vms // File(ISAM): state.dat // File(ISAM): config.sys // Queue(priority): compute // Queue(priority): log // Pathway(LWP): authentication // Pathway(LWP): error processing