//
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
<iostream.h>
#include <stdlib.h>
#include
<time.h>
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