//
Purpose.  Adapter
//
//
Discussion.  The Adapter pattern
//
discusses how to "wrap" the old in-
// terface of a legacy
component, so
// that it can continue to contribute
// in a new
system.  It is about "im-   #include <iostream.h>
// pedance
matching" an old dog with   
#include <stdio.h>
// new tricks (to mix metaphors).  On  
#include <time.h>
// the left, WimpyTime "hasa"
in-
// stance of the legacy component,      class ManlyTime {
// and delegates the "heavy
lifting"    public:
// to
it.  On the right, private           char* getTime() {
//
derivation is used to accomplish          
static char buf[30];
// the same result.                           time_t 
lt;
                                              tm*     ltStruct;
class ManlyTime {                             time( <
);
public:                                       ltStruct =
localtime(<);
   char*
getTime() {                         
strftime( buf, 30, "%H%M",
      static char buf[30];                       ltStruct );
      time_t  lt;                             return buf;
      tm*    
ltStruct;                   
}
      time( <
);                      };
      ltStruct = localtime(<);
      strftime( buf, 30,
"%H%M",        class WimpyTime
:
         ltStruct );                              private
ManlyTime {
      return buf;                       public:
   }                                       char* getTime() {
};                                           
static char buf[30];
                                              char *ptr, mi[3], am[3];
class
WimpyTime {                            
int  hr;
public:                                       ptr =
ManlyTime::getTime();
   char*
getTime() {                         
cout << "old interface time is "
      static char buf[30];                       << ptr <<
endl;
      char *ptr, mi[3],
am[3];                strcpy( mi,
&(ptr[2]) );
      int  hr;                                ptr[2] = '\0';
      ptr = imp_.getTime();                   sscanf( ptr,
"%d", &hr );
      cout
<< "old interface time is "        strcpy( am, "AM" );
         << ptr << endl;                      if (hr > 12) {
      strcpy( mi, &(ptr[2]) );                   hr -= 12;
      ptr[2] = '\0';                             strcpy( am, "PM" ); }
      sscanf( ptr, "%d", &hr
);               sprintf( buf,
"%d:%s %s",
      strcpy(
am, "AM" );                       
hr, mi, am );
      if (hr
> 12) {                         
return buf;
         hr -=
12;                         }
         strcpy( am, "PM" ); }          };
      sprintf( buf, "%d:%s %s",
         hr, mi, am );                  void main( void )
      return buf;                       {
  
}                                      
WimpyTime  newT;
private:                                   char*      ptr;
   ManlyTime  imp_;                        ptr =
newT.getTime();
};                                         cout << "new
interface time is "
                                              << ptr <<
endl;
void main( void )                       }
{
   WimpyTime  newT;                     // old interface time is
1721
   char*      ptr;                      // new interface time is 5:21 PM
   ptr = newT.getTime();
   cout << "new interface time is
"
      << ptr <<
endl;
}
// old interface time is 1709
// new interface
time is 5:09 PM
// Purpose.  Adapter design pattern demo
// 
// Discussion.  LegacyRectangle's interface is not
compatible with the
// system that would like to reuse it.  An abstract base class is created
//
that specifies the desired interface. 
An "adapter" class is defined
// that publicly inherits
the interface of the abstract class, and
// privately inherits the
implementation of the legacy component. 
This
// adapter class "maps" or "impedance
matches" the new interface to the
// old implementation.
#include
<iostream.h>
typedef int Coordinate;
typedef int
Dimension;
/////////////////////////// Desired interface
///////////////////////////
class Rectangle {
public:
   virtual void draw() = 0;
};
///////////////////////////
Legacy component ///////////////////////////
class LegacyRectangle {
public:
   LegacyRectangle( Coordinate x1, Coordinate
y1,
         Coordinate x2,
Coordinate y2 ) {
      x1_ =
x1;  y1_ = y1;  x2_ = x2;  y2_ = y2;
      cout <<
"LegacyRectangle:  create.  (" << x1_ << ","
<< y1_
         <<
") => (" << x2_ << "," << y2_ <<
")" << endl; }
  
void oldDraw() {
      cout
<< "LegacyRectangle: 
oldDraw.  (" << x1_
<< "," << y1_
         << ") => (" << x2_ <<
"," << y2_ << ")" << endl; }
private:
   Coordinate x1_;
   Coordinate y1_;
   Coordinate x2_;
   Coordinate y2_;
};
///////////////////////////
Adapter wrapper ///////////////////////////
class RectangleAdapter :
public Rectangle, private LegacyRectangle {
public:
   RectangleAdapter( Coordinate x, Coordinate
y, Dimension w, Dimension h )
        
: LegacyRectangle( x, y, x+w, y+h ) {
      cout << "RectangleAdapter: create.  (" << x << ","
<< y
         <<
"), width = " << w << ", height = " << h
<< endl; }
   virtual void
draw() {
      cout <<
"RectangleAdapter: draw." << endl;
      oldDraw(); }
};
void
main() {
   Rectangle*  r = new RectangleAdapter( 120, 200, 60, 40
);
   r->draw();
}
//
LegacyRectangle:  create.  (120,200) => (180,240)
//
RectangleAdapter: create.  (120,200),
width = 60, height = 40
// RectangleAdapter: draw.
//
LegacyRectangle:  oldDraw.  (120,200) => (180,240)
//
Purpose.  Adapter design pattern
(External Polymorphism demo)
// 1. Specify the new desired
interface
// 2. Design a "wrapper" class that can
"impedance match" the old to the new
// 3. The client uses (is
coupled to) the new interface
// 4. The adapter/wrapper "maps"
to the legacy implementation
#include <iostream.h>
class
ExecuteInterface { public:                 
// 1. Specify the new i/f
  
virtual ~ExecuteInterface() { }
  
virtual void execute() = 0;
};
template <class
TYPE>                             //
2. Design a "wrapper" or
class ExecuteAdapter : public
ExecuteInterface {  //    "adapter" class
public:
   ExecuteAdapter( TYPE* o, void (TYPE::*m)()
) { object = o;  method =m; }
   ~ExecuteAdapter()                            { delete object; }
   // 4. The adapter/wrapper "maps"
the new to the legacy implementation
  
void execute()             /* the
new */     { (object->*method)();
}
private:                            
   TYPE* object;                                  //
ptr-to-object attribute
   void
(TYPE::*method)();    /* the old */       // ptr-to-member-function
};                                               
//   attribute
// The
old: three totally incompatible classes   
// no common base class,
class Fea { public:                               // no hope of
polymorphism
   ~Fea()        { cout << "Fea::dtor"
<< endl; }
   void doThis() {
cout << "Fea::doThis()" << endl; }
};
class
Feye { public:
   ~Feye()       { cout << "Feye::dtor"
<< endl; }
   void doThat() {
cout << "Feye::doThat()" << endl; }
};
class
Pheau { public:
   ~Pheau()          { cout <<
"Pheau::dtor" << endl; }
   void doTheOther() { cout <<
"Pheau::doTheOther()" << endl; }
};
/* the new
is returned */ ExecuteInterface** initialize() {
   ExecuteInterface** array = new
ExecuteInterface*[3]; /* the old is below */
   array[0] = new ExecuteAdapter<Fea>(   new Fea(),     &Fea::doThis      
);
   array[1] = new
ExecuteAdapter<Feye>(  new
Feye(),    &Feye::doThat      );
   array[2] = new ExecuteAdapter<Pheau>( new Pheau(),   &Pheau::doTheOther );
   return array;
}
void main(
void ) {
   ExecuteInterface**
objects = initialize();
  
for (int i=0; i < 3; i++) objects[i]->execute();  // 3. Client uses the new
                                                    
//    (polymporphism)
   for (i=0; i < 3; i++) delete
objects[i];
   delete
objects;
}
// Fea::doThis()
// Feye::doThat()
//
Pheau::doTheOther()
// Fea::dtor
// Feye::dtor
//
Pheau::dtor