// Purpose. Decorator design pattern lab // // Problem. Inheritance is being used to produce lots of incremental // customizations. This is fine - until all the potential permutations of // options gets out of hand. Another limitation is the static nature of // inheritance. For any particular combination of options to be useable, // the class hierarchy must explicitly implement that combination. It would // be much better if all the individual "options" could each be represented // by their own class, and, the client could dynamically compose her // peculiar list of options at run-time. // // Assignment. // o Add an abstract base class Expression with the single pure virtual // function evaluate(). // o Function should inherit from Expression (but otherwise remain unchanged). // o Add a base class Decorator that inherits from Expression. // o Add an Expression* data member to Decorator (this will be used to remember // the "core" object that this Decorator instance is "wrapping"). // o Decorator needs a constructor to initialize this Expression* data member. // o Decorator's evaluate() should do nothing more than delegate to the // Expression* data member. // o LowCut and HighCut should now inherit from Decorator instead of Function. // o Eliminate MiddlePass. // o Add an Expression* parameter to LowCut's and HighCut's constructors (this // is the "core" object that this "onion skin" is going to be wrapping). // o Use a member initialization list to communicate the Expression* parameter // to the Decorator base class. // o LowCut's and HighCut's evaluate() should now call base class Decorator's // evaluate() instead of Function's (Function is no longer serving as a base // class). // o Now that LowCut and HighCut no longer have an "isa" relationship to // Function (they are now "embellishments" for a core object of type // Function), the "lc" and "hc" local variables in main() must have a // Function* at the "core" of their constructor arguments. This could be // done with an inline dynamic allocation (new Function). // o The MiddlePass class no longer exists. Therefore, the "mp" local variable // in main() will be configured by using a layering of "decorator" objects on // a "core" object. #include #include #include class Function { public: Function() { time_t t; srand((unsigned) time(&t)); } virtual int evaluate() { return rand() % 30; } }; class LowCut : virtual public Function { public: LowCut( int min ) { minimum_ = min; } int evaluate() { int temp = Function::evaluate(); if (temp < minimum_) return minimum_; return temp; } protected: int minimum_; }; class HighCut : virtual public Function { public: HighCut( int max ) { maximum_ = max; } int evaluate() { int temp = Function::evaluate(); if (temp > maximum_) return maximum_; return temp; } protected: int maximum_; }; class MiddlePass : public LowCut, public HighCut { public: MiddlePass( int min, int max ) : LowCut(min), HighCut(max) { } int evaluate() { int temp = LowCut::evaluate(); if (temp > maximum_) return maximum_; return temp; } }; void main( void ) { LowCut lc( 7 ); HighCut hc( 23 ); MiddlePass mp( 10, 20 ); int i; for (i=0; i < 25; i++) cout << lc.evaluate() << " "; cout << endl; for (i=0; i < 25; i++) cout << hc.evaluate() << " "; cout << endl; for (i=0; i < 25; i++) cout << mp.evaluate() << " "; cout << endl; } // 27 18 7 13 19 13 22 16 22 16 17 11 13 13 10 20 22 7 8 23 14 7 29 7 15 // 2 22 23 15 8 16 7 18 7 10 6 21 6 19 3 23 0 20 5 13 23 3 2 6 1 // 18 19 20 20 12 10 14 14 13 14 20 20 20 10 12 18 10 11 10 18 20 20 10 10 10 // // 11 19 26 27 7 7 25 15 10 9 23 8 10 13 20 18 14 7 7 17 7 7 7 22 25 // 11 4 6 23 22 10 15 23 22 2 12 19 19 12 13 18 6 15 6 1 13 1 10 14 23 // 18 20 20 20 10 20 17 10 20 15 20 17 10 16 10 10 10 17 20 20 11 14 20 10 10 // // 7 7 11 29 27 7 11 16 27 15 10 26 27 7 11 28 17 7 7 13 11 20 26 21 29 // 22 23 23 23 3 13 17 13 12 0 23 23 3 11 14 23 13 4 0 23 9 22 23 14 14 // 10 10 10 10 10 10 10 10 19 14 14 10 13 10 11 14 20 16 20 20 20 10 18 18 10