//
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]