bottom prev next

Adapter

Adapter is an impersonating pattern that may be used when one existing data type, adaptee, must be brought into the fold of another existing data type, target, while the two data types are incompatible.

In practice it is often the case that adaptee's source code either can not be modified or is not available altogether.

The Adapter pattern consequences:

  • Target data type can modify adaptee data type's behavior


Sample Problem

Add fax_t to bio_t from Factory chapter, assuming that the bio_t data type and its dependencies existed for a long period of time.

This fax library comes with the fax.h header file, libfax.so shared library and provides the following functionality (not shown here, see Exercises):

  • initFax()

  • uninitFax()

  • dialFaxNumber()

  • acceptFax()

  • sendFax()

  • receiveFax()

  • hangupFax()


Generic Solution Description

1) Add the ability to attach multiple similar but different implementations to the target's data type.

2) Add the adaptee's data type to that of the target.

3) For each public adaptee's interface find the closest target's equivalent and convert the former into the latter.


Sample Solution

Step 1

The target data type, bio_t, already supports the addition of multiple different but similar implementations to a common interface.


Step 2

Use "fax" to select the fax_t-based implementation from the I/O Factory.


Step 3

Convert fax_t to bio_t in libbiofax.c:

- initFax() may or may not have an approptiate bio_t equivalent. We will correlate it with bioConstruct()

- uninitFax() may or may not have an approptiate bio_t equivalent. We will correlate it with bioDestruct()

- dialFaxNumber() and acceptFax() correspond to bioOpen(). We will decide on the format of the address string ahead of time: "send:(555)555-5555" address string, for example, will designate a variable used to send faxes while "receive:(555)555-5555" address string will designate a variable used to receive faxes

- sendFax() corresponds to bioWrite()

- receiveFax() corresponds to bioRead()

- hangupFax() corresponds to bioClose()

In practice number, order and type of arguments of sendFax() and receiveFax() will likely differ from that of bioWrite() and bioRead(). Consequently, bioWriteFax() and bioReadFax() is where the required conversion will take place.

libbiofax.c:

#include <stdio.h> #include <string.h> #include "libbio.h" #include "fax.h" typedef struct { bio_t bioadt; fax_t fax; } biofax_t; extern int bioOpenFax( bio_t*, const char* ); extern ssize_t bioReadFax( bio_t*, void*, size_t ); extern ssize_t bioWriteFax( bio_t*, void*, size_t ); extern int bioCloseFax( bio_t* ); extern void bioDestructFax( bio_t* ); extern size_t bioSizeOffax(); extern bio_t* bioConstructfax( void* ); static bio_t faxAdt = { bioOpenFax, bioReadFax, bioWriteFax, bioCloseFax, bioDestructFax }; extern size_t bioSizeOffax() { return sizeof( biofax_t ); } extern bio_t* bioConstructfax( void* mem ) { biofax_t* biofax = ( biofax_t* )mem; biofax->bioadt = faxAdt; initFax( &biofax->fax ); return &biofax->bioadt; } extern void bioDestructFax( bio_t* bio ) { biofax_t* biofax = ( biofax_t* )bio; bioCloseFax( bio ); uninitFax( &biofax->fax ); } extern int bioOpenFax( bio_t* bio, const char* adrs ) { int r = 0; char* a = strchr( adrs, ':' ); biofax_t* biofax = ( biofax_t* )bio; if ( *adrs == 's' ) { r = dialFaxNumber( &biofax->fax, a + sizeof( ':' ) ); } else { r = acceptFax( &biofax->fax, a + sizeof( ':' ) ); } return r; } extern ssize_t bioReadFax( bio_t* bio, void* b, size_t bsz ) { size_t n; biofax_t* biofax = ( biofax_t* )bio; n = receiveFax( &biofax->fax, b, bsz ); return n; } extern ssize_t bioWriteFax( bio_t* bio, void* b, size_t bsz ) { size_t n; biofax_t* biofax = ( biofax_t* )bio; n = sendFax( &biofax->fax b, bsz ); return n; } extern int bioCloseFax( bio_t* bio ) { biofax_t* biofax = ( biofax_t* )bio; hangupFax( &biofax->fax ); return 0; }


Step 4

Recalling Chained Linking chapter add libfax.so to the I/O Factory's build instructions.

SLBTF:

gcc -D_GNU_SOURCE -g -shared -o libbio.so \ libbio.o \ libbiofile.o \ libbiotcpv4.o \ libbiotcpv6.o \ libbiofax.o \ -lfax \ -ldl

MLBTF and MLRTF:

gcc -g -shared -o libbiofax.so libbiofax.o -lfax


Step 5

Exercise the Adapter pattern with the sample program:

./bio fax "receive:(555)555-5555"


Exercises

1) Carry out a mock (or real) implementation of fax_t as described in Sample Problem section.

\(\blacksquare\)

top prev next