// Purpose. Composite design pattern lab. // // Problem. Approach is now more space efficient, but casting and type // checking are required to coerce the compiler. The abstraction needs to // be improved so that Primitive and Composite can be treated // transparently in a sibling context, while still maintaining their // specialization. // // Assignment. // o Create a class Component to serve as a base class. Primitive and // Composite should inherit from Component. // o Move anything that is (or needs to be) common in both Primitive and // Composite up into Component. // o Currently class Composite is coupled to itself (the argument to add() and // the children private data member). It needs to be coupled only to its // abstract base class. // o You can now remove: NodeType, reportType(), the casting in main() and // Composite::traverse(), and the "type checking" in Composite::traverse() #include enum NodeType { LEAF, INTERIOR }; class Primitive { public: Primitive( int val ) : value(val), type(LEAF) { } NodeType reportType() { return type; } void traverse() { cout << value << " "; } private: int value; NodeType type; }; class Composite { public: Composite( int val ) : value(val), type(INTERIOR) { total = 0; } NodeType reportType() { return type; } void add( Composite* c ) { children[total++] = c; } void traverse() { cout << value << " "; for (int i=0; i < total; i++) if (children[i]->reportType() == LEAF) ((Primitive*) children[i])->traverse(); else children[i]->traverse(); } private: int value; NodeType type; int total; Composite* children[99]; }; void main( void ) { Composite first(1), second(2), third(3); first.add( &second ); first.add( &third ); first.add( (Composite*) new Primitive(4) ); second.add( (Composite*) new Primitive(5) ); second.add( (Composite*) new Primitive(6) ); third.add( (Composite*) new Primitive(7) ); first.traverse(); cout << endl; } // 1 2 5 6 3 7 4