如果要构造一个组成部件很多的对象,即所谓的aggregate,可能要使用Director - Builder模式。
Director也叫Reader或Parser,负责解析输入,然后调用Builder相应的函数来构造对象相应的部件。
Builder模式的特征是,在构造对象时,一步步逐渐完成,而不是用一个函数一下子实现。
把整个构造过程抽象出N步,是为了让每一个步骤有多种实现方式。这样,最后构造出来的对象就会有多种表现形式。
所以,Builder模式适用的场合是:一种输入,多种可能的输出。
客户需要创建Reader和Builder各一个,然后把二者耦合在一起。给Reader输入,让其启动construct动作,最后找Builder得到具体的输出。
enum PersistenceType { File, Queue, Pathway }; struct PersistenceAttribute { PersistenceType type; char value[30]; }; // 这是一个平台无关的类,是Builder要创建的对象 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]; }; // 平台相关的操作都封装到了Builder的各个派生类里 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; }