//
Purpose. Strategy #include <iostream.h>
// #include
<stdlib.h>
// Discussion.
The class Stat has a #include
<time.h>
// Bubble sort algorithm hard-wired in
// it. It would be nice if the choice class SortImp;
// of algorithm were
configurable.
// The Strategy pattern suggests "de- class Stat {
// fine a family of
algo's, encapsu- public:
// late
each one, and make them inter-
Stat();
// changeable" via an abstract base void upGrade();
// class. void
downGrade();
void readVector( int[],
int );
class Stat { /* Bubble
sort */ int getMin() { return
min_; }
public: int getMax() { return max_;
}
void readVector( int v[], int
n ) { int getMed() { return med_;
}
sort_( v, n ); private:
min_ = v[0]; max_ = v[n-1]; int
min_, max_, med_;
med_ =
v[n/2]; } SortImp* imp_;
int getMin()
{ return min_; } };
int getMax() { return max_; }
int getMed() { return med_; } class SortImp { public:
private: virtual
void sort( int[], int ) = 0;
int
min_, max_, med_;
};
void sort_( int v[],
int n ) {
for (int i=n-1; i
> 0; i--) class SortBubble :
public SortImp {
for (int
j=0; j < i; j++) public:
if (v[j] > v[j+1]) { void sort( int v[], int n );
int t = v[j]; };
v[j] = v[j+1];
v[j+1] = t; } class SortShell : public SortImp {
cout << "Bubble: "; public:
for (int k=0; k < n; k++) void sort( int v[], int n );
cout << v[k] << ' '; };
cout << endl;
}
#include "strategy2.inc"
};
Stat::Stat() { imp_ = new SortBubble; }
void main( void ) void Stat::upGrade()
{ delete imp_;
{ imp_ = new SortShell;
}
const int NUM = 9; void Stat::downGrade() {
delete imp_;
int array[NUM]; imp_ = new SortBubble; }
time_t
t; void
Stat::readVector(int v[], int n) {
srand((unsigned) time(&t)); imp_->sort( v, n );
cout << "Vector: "; min_ = v[0];
max_ = v[n-1];
for (int
i=0; i < NUM; i++) { med_ = v[n/2]; }
array[i] = rand() % 9 + 1;
cout << array[i] << ' ';
} void main( void )
cout << endl; {
const int NUM = 9;
Stat obj; int array[NUM];
obj.readVector( array, NUM ); time_t t;
cout <<
"min is " << obj.getMin()
srand((unsigned) time(&t));
<< ", max is " << obj.getMax() cout << "Vector:
";
<< ",
median is " << obj.getMed()
for (int i=0; i < NUM; i++) {
<< endl; array[i] = rand() % 9 + 1;
}
cout << array[i] << ' '; }
cout <<
endl;
/***** current implementation *****/
// Vector: 6 9 9 8 6 5 7 9
2 Stat obj;
// Bubble: 2 5 6 6 7 8 9 9 9 obj.upGrade();
// min is
2, max is 9, median is 7
obj.readVector( array, NUM );
/*** an upgraded implementation
***/ cout << "min is
" << obj.getMin()
// Vector: 4 8 6 4 6 7 4 7 2 << ", max is
" << obj.getMax()
// Shell:
2 4 4 4 6 6 7 7 8
<< ", median is " << obj.getMed()
// min is
2, max is 8, median is 6
<< endl;
}
//
Purpose. Strategy (template #include <iostream>
// approach) #include <cstdlib>
// A
template can be used to configure
#include <ctime>
// a client with a Strategy. This
using namespace std;
// technique is appropriate if: 1) the
//
Strategy can be selected at com-
template<class STRATEGY>
// pile-time, and 2) it does not
have class Stat {
// to be
changed at run-time. With a public:
// template, there is no need
to spe- void readVector( int v[],
int n ) {
// cify the interface in a SortImp imp_.sort( v, n );
// base class. The Stat class now has min_ = v[0]; max_ = v[n-1];
// an instance of the sort object, in- med_ = v[n/2]; }
// stead of a ptr
to the base class. int getMin() {
return min_; }
// The inheritance approach offers int getMax() { return max_; }
//
more options and expressiveness.
int getMed() { return med_; }
// The template approach offers
mildly private:
// better
efficiency.
int min_, max_, med_;
STRATEGY imp_;
class Stat
{ /* Bubble sort */ };
public:
void readVector( int v[], int n ) { class SortBubble {
sort_( v, n ); public:
min_ = v[0]; max_ =
v[n-1]; void sort( int v[], int n
);
med_ = v[n/2]; } };
int getMin() { return min_; }
int getMax() { return max_; } class SortShell {
int getMed() { return med_; } public:
private: void sort(
int v[], int n );
int min_,
max_, med_; };
void sort_( int v[], int n ) {
for (int i=n-1; i > 0; i--) #include
"strategy2.inc"
for (int j=0; j < i; j++)
if (v[j] > v[j+1]) { void main( void ) {
int t = v[j]; const int NUM = 9;
v[j] = v[j+1]; int
array[NUM];
v[j+1] = t; }
time_t t;
cout << "Bubble: "; srand((unsigned)
time(&t));
for (int k=0;
k < n; k++) cout <<
"Vector: ";
cout
<< v[k] << ' ';
for (int i=0; i < NUM; i++) {
cout << endl; array[i] = rand() % 9 + 1;
} cout << array[i]
<< ' '; }
}; cout << endl;
void
main( void ) {
Stat<SortBubble>
obj;
const int NUM =
9; obj.readVector(
array, NUM );
int array[NUM]; cout << "min is " <<
obj.getMin()
time_t t; << ", max is "
<< obj.getMax()
srand((unsigned) time(&t)); << ", median is " <<
obj.getMed()
cout <<
"Vector: ";
<< endl;
for (int
i=0; i < NUM; i++) {
array[i] = rand() % 9 + 1;
Stat<SortShell> two;
cout << array[i] << ' ';
} two.readVector( array, NUM
);
cout << endl; cout <<
"min is " << two.getMin()
<< ", max
is " << two.getMax()
Stat obj; <<
", median is " << two.getMed()
obj.readVector( array, NUM ); << endl;
cout << "min is " << obj.getMin() }
<< ", max is " << obj.getMax()
<< ", median is "
<< obj.getMed() // Vector: 3 5 4 9 7 1 4 9 2
<< endl; // Bubble: 1 2 3 4 4 5 7 9 9
} // min
is 1, max is 9, median is 4
// Shell: 1 2 3 4 4 5 7 9 9
// Vector: 6 9 9 8 6
5 7 9 2 // min is 1, max is
9, median is 4
// Bubble: 2 5 6 6 7 8 9 9 9
// min is 2, max is 9,
median is 7
// Purpose.
Strategy design pattern demo
//
// Discussion. The Strategy pattern suggests: encapsulating
an algorithm
// in a class hierarchy, having clients of that algorithm
hold a pointer
// to the base class of that hierarchy, and delegating all
requests for
// the algorithm to that "anonymous" contained
object. In this example,
// the
Strategy base class knows how to collect a paragraph of input and
//
implement the skeleton of the "format" algorithm. It defers some
// details of each
individual algorithm to the "justify" member which is
//
supplied by each concrete derived class of Strategy. The TestBed class
// models an application class that would
like to leverage the services of
// a run-time-specified derived
"Strategy" object.
#include <iostream.h>
#include
<fstream.h>
#include <string.h>
class
Strategy;
class TestBed {
public:
enum StrategyType { Dummy, Left, Right,
Center };
TestBed() { strategy_ = NULL; }
void setStrategy( int type, int width
);
void doIt();
private:
Strategy*
strategy_;
};
class Strategy {
public:
Strategy( int width ) : width_( width ) {
}
void format() {
char line[80], word[30];
ifstream inFile( "quote.txt", ios::in );
line[0] = '\0';
inFile >> word;
strcat( line, word );
while (inFile >> word)
{
if (strlen(line) + strlen(word) + 1 > width_)
justify( line );
else
strcat( line, " " );
strcat( line, word );
}
justify( line );
}
protected:
int width_;
private:
virtual void justify( char* line ) =
0;
};
class LeftStrategy : public Strategy {
public:
LeftStrategy( int width ) : Strategy( width
) { }
private:
/* virtual
*/ void justify( char* line ) {
cout << line << endl;
line[0] = '\0'; }
};
class RightStrategy :
public Strategy {
public:
RightStrategy( int width ) : Strategy( width ) { }
private:
/* virtual */ void justify( char* line )
{
char buf[80];
int offset = width_
- strlen( line );
memset(
buf, ' ', 80 );
strcpy(
&(buf[offset]), line );
cout << buf << endl;
line[0] = '\0'; }
};
class CenterStrategy :
public Strategy {
public:
CenterStrategy( int width ) : Strategy( width ) { }
private:
/* virtual */ void justify( char* line )
{
char buf[80];
int offset = (width_
- strlen( line )) / 2;
memset( buf, ' ', 80 );
strcpy( &(buf[offset]), line );
cout << buf << endl;
line[0] = '\0'; }
};
void
TestBed::setStrategy( int type, int width ) {
delete strategy_;
if (type == Left) strategy_ = new LeftStrategy( width
);
else if (type == Right) strategy_ = new RightStrategy( width
);
else if (type == Center)
strategy_ = new CenterStrategy( width ); }
void TestBed::doIt() {
strategy_->format(); }
void main() {
TestBed
test;
int answer, width;
cout << "Exit(0) Left(1)
Right(2) Center(3): ";
cin
>> answer;
while
(answer)
{
cout << "Width: ";
cin >> width;
test.setStrategy( answer, width );
test.doIt();
cout << "Exit(0) Left(1)
Right(2) Center(3): ";
cin >> answer;
}
return 0;
}
//
Exit(0) Left(1) Right(2) Center(3): 2
// Width: 75
// The important lesson we have learned is
that development for reuse is
//
complex. If making a good design is difficult, then making a good
reusable
// design is even
harder, and any amount of process description cannot
// substitute for the
skill, imagination, and experience of a good designer. A
// process can
only support the creative work, and ensure that things are done
// and recorded
properly. [Karlsson et al, REBOOT]
// Exit(0) Left(1) Right(2) Center(3):
3
// Width: 75
// The
important lesson we have learned is that development for reuse is
//
complex. If making a good design is difficult, then making a good
reusable
// design is even
harder, and any amount of process description cannot
// substitute for the
skill, imagination, and experience of a good designer. A
// process can
only support the creative work, and ensure that things are done
// and recorded properly.
[Karlsson et al, REBOOT]