SDSU CS 635: Advanced Object-Oriented Design & Programming
Spring Semester, 1998
Adapter

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 21-Apr-98

Contents of Doc 21, Adapter


CS 635 - Doc 21 Adapter

References slide # 1
Motivating Adapter slide # 2
Adapter slide # 7
...Consequences slide # 11
...Adapter Verses State slide # 15


References

Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, Addison Wesley, 1995, pp 139-150

sdsu.net.CGI at:
http://www.eli.sdsu.edu/java-SDSU/sdsu.net.CGI.html

CGI Environment Variables at: http://hoohoo.ncsa.uiuc.edu/cgi/env.html


Doc 21, Adapter Slide # 2

Motivating Adapter

Java CGI & Servlets

Both Java CGI and servlets are used for server-side processing of certain HTML requests, like processing HTML forms

Servlets have greater functionality and are faster, but require special Web servers or servers with special extensions

To help write Java CGI programs there is class sdsu.net.CGI

Adapters would be useful in moving code between servers to avoid having to rewrite the code

There are various issues in writing such adapters
One issue is access to the CGI environment variables

There are about 20 common CGI environment variables

In servlets one has a HttpRequest class that has a getX() method for each CGI environment variable

sdsu.net.CGI class returns a hash table with one entry per CGI environment variable


Doc 21, Adapter Slide # 3
Problem

Say we have a number of Java CGI programs we wish to run as servlets

Do we have to rewrite all the CGI programs?

Solution
We have a class, HttpRequest, which has getX() methods

We have code that uses a class with get( "X" ) method

We can write a wrapper around HttpRequest to make it act like a hash table


Doc 21, Adapter Slide # 4

The Wrapper or Adapter
class CGIAdapter extends Hashtable { Hashtable CGIvariables = new Hashtable( 20); public CGIAdapter( HttpRequest CGIEnvironment ) { CGIvariables.put( "AUTH_TYPE" , CGIEnvironment.getAuthType()); CGIvariables.put( "REMOTE_USER" , CGIEnvironment.getRemoteUser()); etc. } public Object get(Object key) { return CGIvariables.get( key ); } etc. }

Doc 21, Adapter Slide # 5
How does the CGI code get CGIAdapter?

In the CGI code one normally uses:

sdsu.net.CGI cgiGateWay = sdsu.net.CGI.getInstance();

Hashtable cgiVariables =
     cgiGateWay.getCGIEnvironmentVariables();

We now have to make an subclass of sdsu.net.CGI whose getCGIEnvironmentVariables returns CGIAdapter

To avoid more CGI details the complete code is not shown


Doc 21, Adapter Slide # 6
Going the other Direction

Adapting servlet code to normal CGI requires extracting the CGI environment variables out of the hash table and putting them into an object that implements the public interface of the HttpRequest class


class HTTPAdapter extends HttpRequest
     {
     Hashtable CGIvariables;
     
     public HTTPAdapter( Hashtable CGIEnvironment )
          {
          CGIvariables = CGIEnvironment;
          }
     
     public String getAuthType()
          {
          return (String) CGIvariables.get( "AUTH_TYPE" );
          }
          
     public String getRemoteUser()
          {
          return (String) CGIvariables.get( "REMOTE_USER" );
          }
          
          etc. 
     }


Doc 21, Adapter Slide # 7

Adapter


The adapter pattern converts the interface of a class into another interface.


Use the Adapter pattern when

Adapter has two form:
Class Adapter
Object Adapter


Doc 21, Adapter Slide # 8
Class Adapter

Class Adapter


Object Adapter

Object Adapter


Doc 21, Adapter Slide # 9
Class Adapter Example

class OldSquarePeg {
     public:
          void squarePegOperation()
               { do something }
}

class RoundPeg {
     public:
          void virtual roundPegOperation = 0;
}

class PegAdapter: private OldSquarePeg, 
                    public RoundPeg  {
     public:
          void virtual roundPegOperation()  {
               add some corners;
               squarePegOperation();
          }
}
     
void clientMethod() {
     RoundPeg* aPeg = new PegAdapter();
     aPeg->roundPegOperation();
}

Doc 21, Adapter Slide # 10
Object Adapter Example

class OldSquarePeg     {
     public:
          void squarePegOperation() { do something }
     }

class RoundPeg     {
     public:
          void virtual roundPegOperation = 0;
     }

class PegAdapter:  public RoundPeg     {
     private:
          OldSquarePeg* square;
          
     public:
          PegAdapter()  { square = new OldSquarePeg; }
               
          void virtual roundPegOperation()     {
               add some corners;
               square->squarePegOperation();
               }
     }

Doc 21, Adapter Slide # 11

Consequences


A Class adapter uses inheritance so


An object adapter uses object composition so


Other issues:



Doc 21, Adapter Slide # 12
How Much Adapting does the Adapter do?

The adapter may have to work very little or a great deal to adapt the Adaptee to the Target

The Adapter may just map one operation to another

class PegAdapter:  public RoundPeg     {
     private:
          OldSquarePeg* square;
          
     public:
          PegAdapter()     { square = new OldSquarePeg;}
               
          void roundPegOperation()     {
               square->squarePegOperation();
          }
}

The Adapter may have to work hard if the Target operation does not have a comparable operation in the Adaptee

Doc 21, Adapter Slide # 13
Pluggable Adapters

In the CGI example we adapted a class with getX() methods to a hash table interface

It is likely that we may adapt a class with getX() methods to a hashtable in the future

It would be nice to write one class to do all such adapting

This class would be given a list of keys to getX methods and an Adaptee object

HttpRequest CGIEnvironment = getHttpRequest();
PluggableHashAdapter sample = 
     new PluggableHashAdapter( CGIEnvironment );

sample.adapt( "AUTH_TYPE" , getAuthType );
sample.adapt( "REMOTE_USER" , getRemoteUser );
etc.

sample.get( "REMOTE_USER" );

Pluggable Adapters are used in interface components, where we know in advance we will adapt the component to other interfaces

Pluggable Adapters are common in Smalltalk, were it is easier to map strings to method calls


Doc 21, Adapter Slide # 14
Using two-way Adapter

In the SquarePeg-RoundPeg example the SquarePeg is adapted to the RoundPeg

So a SquarePeg can be used where a RoundPeg is needed, but not the other way around.

A two-way adapter would also allow a RoundPeg be used in place of the SquarePeg

class OldSquarePeg {
     public:
          void virtual squarePegOperation() { blah }
}

class RoundPeg {
     public:
          void virtual roundPegOperation() { blah }
}

class PegAdapter: public OldSquarePeg, RoundPeg {
     public:
          void virtual roundPegOperation() {
               add some corners;
               squarePegOperation();
          }
          void virtual squarePegOperation() {
               add some corners;
               roundPegOperation();
          }
}

Doc 21, Adapter Slide # 15

Adapter Verses State


Both Adapter and State forward requests to an instance object

That is both use object composition

What is the difference?

Adapter
Object Adapter


State
State
visitors since 14-Apr-98