// Purpose.  Template Method            // Discussion.  On the left, we're
                                        // starting with 2 sorts that are very
#include <iostream.h>                   // similar.  If we could "customize" a
#include <stdlib.h>                     // single sort implementation, we could
#include <time.h>                       // enjoy reuse.  "Template Method de-
                                        // fines an algorithm in terms of ab-
class SortUp {  ///// Shell sort /////  // stract operations that subclasses
public:                                 // override to provide concrete beha-
   void doIt( int v[], int n ) {        // vior."  Here, doIt() is the algo-
      for (int g = n/2; g > 0; g /= 2)  // rithm, and needSwap() is the ab-
         for (int i = g; i < n; i++)    // stract operation.
            for (int j = i-g; j >= 0;
                              j -= g)   class Sort {  ////// Shell sort //////
               if (v[j] > v[j+g])       public:
                  doSwap(v[j],v[j+g]);     void doIt( int v[], int n ) {
   }                                          for (int g = n/2; g > 0; g /= 2)
private:                                         for (int i = g; i < n; i++)
   void doSwap(int& a,int& b) {                     for (int j = i-g; j >= 0;
      int t = a; a = b; b = t; }                                      j -= g)
};                                                     if (needSwap(v[j],
                                                                    v[j+g]))
class SortDown {                                          doSwap(v[j],
public:                                                          v[j+g]);
   void doIt( int v[], int n ) {           }
      for (int g = n/2; g > 0; g /= 2)  private:
         for (int i = g; i < n; i++)       virtual int needSwap(int,int) = 0;
            for (int j = i-g; j >= 0;      void doSwap(int& a,int& b) {
                              j -= g)         int t = a; a = b; b = t; }
               if (v[j] < v[j+g])       };
                  doSwap(v[j],v[j+g]);
   }                                    class SortUp : public Sort {
private:                                   int needSwap(int a, int b) {
   void doSwap(int& a,int& b) {               return (a > b); }
      int t = a; a = b; b = t; }        };
};                                      class SortDown : public Sort {
                                           int needSwap(int a, int b) {
void main( void )                             return (a < b); }
{                                       };
   const int NUM = 10;
   int       array[NUM];                void main( void )
   time_t    t;                         {
   srand((unsigned) time(&t));             const int NUM = 10;
   for (int i=0; i < NUM; i++) {           int       array[NUM];
      array[i] = rand() % 10 + 1;          time_t    t;
      cout << array[i] << ' '; }           srand((unsigned) time(&t));
   cout << endl;                           for (int i=0; i < NUM; i++) {
                                              array[i] = rand() % 10 + 1;
   SortUp  upObj;                             cout << array[i] << ' '; }
   upObj.doIt( array, NUM );               cout << endl;
   for (int u=0; u < NUM; u++)
      cout << array[u] << ' ';             SortUp  upObj;
   cout << endl;                           upObj.doIt( array, NUM );
                                           for (int u=0; u < NUM; u++)
   SortDown  downObj;                         cout << array[u] << ' ';
   downObj.doIt( array, NUM );             cout << endl;
   for (int d=0; d < NUM; d++)
      cout << array[d] << ' ';             SortDown  downObj;
   cout << endl;                           downObj.doIt( array, NUM );
}                                          for (int d=0; d < NUM; d++)
                                              cout << array[d] << ' ';
// 3 10 5 5 5 4 2 1 5 9                    cout << endl;
// 1 2 3 4 5 5 5 5 9 10                 }
// 10 9 5 5 5 5 4 3 2 1
                                        // 1 6 6 2 10 9 4 10 6 4
                                        // 1 2 4 4 6 6 6 9 10 10
                                        // 10 10 9 6 6 6 4 4 2 1



// Purpose.  No reuse

#include <iostream>
using namespace std;

class One {
   void a() { cout << "a  "; }
   void b() { cout << "b  "; }
   void c() { cout << "c  "; }
   void d() { cout << "d  "; }
   void e() { cout << "e  "; }
public:
   void execute() { a();  b();  c();  d();  e(); }
};

class Two {
   void a()  { cout << "a  "; }
   void _2() { cout << "2  "; }
   void c()  { cout << "c  "; }
   void _4() { cout << "4  "; }
   void e()  { cout << "e  "; }
public:
   void execute() { a();  _2();  c();  _4();  e(); }
};

void main( void ) {
   One first;
   first.execute();
   cout << '\n';
   Two second;
   second.execute();
   cout << '\n';
}

// a  b  c  d  e
// a  2  c  4  e




// Purpose.  Template Method design pattern

// 1. Standardize the skeleton of an algorithm in a base class "template method"
// 2. Steps requiring peculiar implementations are "placeholders" in base class
// 3. Derived classes implement placeholder methods

#include <iostream>
using namespace std;

class Base {
   void a() { cout << "a  "; }
   void c() { cout << "c  "; }
   void e() { cout << "e  "; }
   // 2. Steps requiring peculiar implementations are "placeholders" in base class
   virtual void ph1() = 0;
   virtual void ph2() = 0;
public:
   // 1. Standardize the skeleton of an algorithm in a base class "template method"
   void execute() {  a();  ph1();  c();  ph2();  e(); }
};

class One : public Base {
   // 3. Derived classes implement placeholder methods
   /*virtual*/ void ph1() { cout << "b  "; }
   /*virtual*/ void ph2() { cout << "d  "; }
};

class Two : public Base {
   /*virtual*/ void ph1() { cout << "2  "; }
   /*virtual*/ void ph2() { cout << "4  "; }
};

void main( void ) {
   Base* array[] = { &One(), &Two() };
   for (int i=0; i < 2; i++) {
      array[i]->execute();
      cout << '\n';
}  }

// a  b  c  d  e
// a  2  c  4  e




// Purpose. Template Method design pattern

// 1. Standardize the skeleton of an algorithm in a base class "template method"
// 2. Steps requiring peculiar implementations are "placeholders" in base class
// 3. Derived classes implement placeholder methods

#include <iostream>
#include <string>
using namespace std;

class StandardAlgorithm {
   // 3. Steps requiring peculiar implementations are "placeholders" in base class
   virtual string preprocess( char* ) = 0;
   virtual bool   validate( char )    = 0;
public:
   // 1. Standardize the skeleton of algorithm in base class "template method"
   string process( char* in ) {
      string str = preprocess( in );
      for (int i=0; i < str.size(); i++)
         if ( ! validate( str[i] )) return "not valid";
      return str;
}  };

class Alphabetic : public StandardAlgorithm {
   /*virtual*/ string preprocess( char* in ) {
      string s( in );
      for (int i=0; i < s.size(); i++)
         if (s[i] >= 'A' && s[i] <= 'Z' || s[i] == ' ') /* empty */ ;
         else if (s[i] >= 'a' && s[i] <= 'z')           s[i] = s[i] - 32;
         else                                           s[i] = '_';
      return s;
   }
   /*virtual*/ bool validate( char ch ) {
      if (ch >= 'A' && ch <= 'Z' || ch == ' ') return true;
      else return false;
}  };

class Numeric : public StandardAlgorithm {
   /*virtual*/ string preprocess( char* in ) { return in; }
   /*virtual*/ bool validate( char ch ) {
      if (ch >= '0' && ch <= '9') return true;
      else return false;
}  };

void main( void ) {
   StandardAlgorithm* types[] = { &Alphabetic(), &Numeric() };
   char buf[20];
   while (true) {
      cout << "Input: ";
      cin.getline( buf, 20 );
      if ( ! strcmp( buf, "quit" )) break;
      for (int i=0; i < 2; i++)
         cout << "   " << types[i]->process( buf ) << '\n';
}  }

// Input: Hello World
//    HELLO WORLD
//    not valid
// Input: 12345
//    not valid
//    12345
// Input: 4.2e3
//    not valid
//    not valid
// Input: quit




// Purpose. Template Method design pattern

// 1. Standardize the skeleton of an algorithm in a base class "template" method
// 2. Common implementations of individual steps are defined in the base class
// 3. Steps requiring peculiar implementations are "placeholders" in base class
// 4. Derived classes can override placeholder methods
// 5. Derived classes can override implemented methods
// 6. Derived classes can override and "call back to" base class methods

#include <iostream>
using namespace std;

class A {
public:
   // 1. Standardize the skeleton of an algorithm in a "template" method
   void findSolution() {
      stepOne();
      stepTwo();
      stepThr();
      stepFor();
   }
protected:
   virtual void stepFor() { cout << "A.stepFor" << '\n'; }
private:
   // 2. Common implementations of individual steps are defined in base class
   void stepOne() { cout << "A.stepOne" << '\n'; }
   // 3. Steps requiring peculiar impls are "placeholders" in the base class
   virtual void stepTwo() = 0;
   virtual void stepThr() = 0;
};

class B : public A {
   // 4. Derived classes can override placeholder methods
   // 1. Standardize the skeleton of an algorithm in a "template" method
   /*virtual*/ void stepThr() {
      step3_1();
      step3_2();
      step3_3();
   }
   // 2. Common implementations of individual steps are defined in base class
   void step3_1() { cout << "B.step3_1" << '\n'; }
   // 3. Steps requiring peculiar impls are "placeholders" in the base class
   virtual void step3_2() = 0;
   void step3_3() { cout << "B.step3_3" << '\n'; }
};

class C : public B {
   // 4. Derived classes can override placeholder methods
   /*virtual*/ void stepTwo() { cout << "C.stepTwo" << '\n'; }
   void step3_2() { cout << "C.step3_2" << '\n'; }
   // 5. Derived classes can override implemented methods
   // 6. Derived classes can override and "call back to" base class methods
   /*virtual*/ void stepFor() {
      cout << "C.stepFor" << '\n';
      A::stepFor();
}  };

void main( void ) {
   C algorithm;
   algorithm.findSolution();
}

// A.stepOne
// C.stepTwo
// B.step3_1
// C.step3_2
// B.step3_3
// C.stepFor
// A.stepFor




// Purpose.  Template Method design pattern demo.
//
// Discussion.  The "template method" establishes the steps to be
// performed.  All standard, or invariant, steps have their implementation
// provided by the abstract base class.  All variable steps are not
// defined in the base class, but must be defined by concrete derived
// classes.  "stepFour" below is an embellishment on the design pattern
// where the base class provides a default implementation, and then the
// derived class may extend that method by: overriding the method,
// "calling-back" to the base class to leverage its implementation, and
// then adding its own peculiar behavior.

#include <iostream.h>

class IncompleteAlgorithm {
public:
   void doIt() {       // this is the Template Method
      stepOne();       // invariant, standard
      stepTwo();       // invariant, standard
      stepThree();     // variable,  supplied by subclass
      stepFour(); }    // variable,  default provided
private:
   void stepOne() {
      cout << "IncompleteAlgorithm::stepOne" << endl; }
   void stepTwo() {
      cout << "IncompleteAlgorithm::stepTwo" << endl; }
   virtual void stepThree() = 0;
protected:
   virtual void stepFour() {
      cout << "IncompleteAlgorithm::stepFour" << endl; }
};

class FillInTheTemplate : public IncompleteAlgorithm {
   /* virtual */ void stepThree() {
      cout << "FillInTheTemplate::stepThree" << endl; }
   /* virtual */ void stepFour() {
      IncompleteAlgorithm::stepFour();
      cout << "FillInTheTemplate::stepFour" << endl; }
};

void main() {
   FillInTheTemplate  theThingToDo;
   theThingToDo.doIt();
}

// IncompleteAlgorithm::stepOne
// IncompleteAlgorithm::stepTwo
// FillInTheTemplate::stepThree
// IncompleteAlgorithm::stepFour
// FillInTheTemplate::stepFour




// Purpose.  Template Method design pattern demo
//
// romanNumeral ::= {thousands} {hundreds} {tens} {ones}
// thousands, hundreds, tens, ones ::= nine | four | {five} {one} {one} {one}
// nine ::= "CM" | "XC" | "IX"
// four ::= "CD" | "XL" | "IV"
// five ::= 'D' | 'L' | 'V'
// one  ::= 'M' | 'C' | 'X' | 'I'

#include <iostream>
#include <string>
using namespace std;
class Thousand;  class Hundred;  class Ten;  class One;

class RNInterpreter {
public:
   static int interpret( string input );
   void interpret( string& input, int& total ) {               // Template Method
      int index = 0;
      if (input.substr(0,2) == nine()) {
         total += 9 * multiplier();
         index += 2;
      } else if (input.substr(0,2) == four()) {
         total += 4 * multiplier();
         index += 2;
      } else {
         if (input[0] == five()) {
            total += 5 * multiplier();
            index = 1;
         }
         for (int end = index + 3 ; index < end; index++)
            if (input[index] == one())
               total += 1 * multiplier();
            else break;
      }
      // remove all leading chars processed
      input.replace( 0, index, "" );
   }
private:
   virtual char one()        = 0;   virtual string four() = 0;  // placeholders
   virtual char five()       = 0;   virtual string nine() = 0;  // placeholders
   virtual int  multiplier() = 0;                               // placeholders
   static Thousand thousands;       static Hundred hundreds;
   static Ten      tens;            static One     ones;
};

class Thousand : public RNInterpreter {
   char  one()        { return 'M'; }    string four() { return ""; }
   char  five()       { return '\0'; }   string nine() { return ""; }
   int   multiplier() { return 1000; }
};
class Hundred : public RNInterpreter {
   char  one()        { return 'C'; }   string four() { return "CD"; }
   char  five()       { return 'D'; }   string nine() { return "CM"; }
   int   multiplier() { return 100; }
};
class Ten : public RNInterpreter {
   char  one()        { return 'X'; }   string four() { return "XL"; }
   char  five()       { return 'L'; }   string nine() { return "XC"; }
   int   multiplier() { return 10; }
};
class One : public RNInterpreter {
   char  one()        { return 'I'; }   string four() { return "IV"; }
   char  five()       { return 'V'; }   string nine() { return "IX"; }
   int   multiplier() { return 1; }
};

Thousand RNInterpreter::thousands;
Hundred  RNInterpreter::hundreds;
Ten      RNInterpreter::tens;
One      RNInterpreter::ones;

/*static*/ int RNInterpreter::interpret( string input ) {
   int total = 0;
   thousands.interpret( input, total );
   hundreds.interpret( input, total );
   tens.interpret( input, total );
   ones.interpret( input, total );
   // if any input remains, the input was invalid, return 0
   if (input != "") return 0;
   return total;
}

void main( void ) {
   string  input;
   cout << "Enter Roman Numeral: ";
   while (cin >> input) {
      cout << "   interpretation is " << RNInterpreter::interpret( input ) << endl;
      cout << "Enter Roman Numeral: ";
}  }

// Enter Roman Numeral: MCMXCVI
//    interpretation is 1996
// Enter Roman Numeral: MMMCMXCIX
//    interpretation is 3999
// Enter Roman Numeral: MMMM
//    interpretation is 0
// Enter Roman Numeral: MDCLXVIIII
//    interpretation is 0
// Enter Roman Numeral: CXCX
//    interpretation is 0
// Enter Roman Numeral: MDCLXVI
//    interpretation is 1666
// Enter Roman Numeral: DCCCLXXXVIII
//    interpretation is 888