[Description] the adapter mode adapts the interface of an object to the interface expected by another object.
[UML diagram]
Figure 1 Apater Mode
(1) known Apatee class, which provides the implementation of the draw line function;
(2) now the user needs to draw points. We know that if the starting point and ending point coordinates of the draw line function are the same, it is actually equivalent to drawing points. Therefore, the adapter mode is used to adapt the draw line function to the draw point function.
[Code list]
Apatee. h
[Html]
# Ifndef APATEE_H
# Define APATEE_H
Class Apatee
{
Public:
Apatee ();
Public:
Void draw (int x0, int y0, int x1, int y1 );
};
# Endif // APATEE_H
# Ifndef APATEE_H
# Define APATEE_H
Class Apatee
{
Public:
Apatee ();
Public:
Void draw (int x0, int y0, int x1, int y1 );
};
# Endif // APATEE_H
Apatee. cpp
[Html]
# Include <QDebug>
# Include "apatee. h"
Apatee: Apatee ()
{
QDebug () <"construct Apatee ";
}
Void Apatee: draw (int x0, int y0, int x1, int y1)
{
QDebug () <QString ("Apatee: draw (int % 1, int % 2, int % 3, int % 4 )"). arg (x0 ). arg (y0 ). arg (x1 ). arg (y1 );
}
# Include <QDebug>
# Include "apatee. h"
Apatee: Apatee ()
{
QDebug () <"construct Apatee ";
}
Void Apatee: draw (int x0, int y0, int x1, int y1)
{
QDebug () <QString ("Apatee: draw (int % 1, int % 2, int % 3, int % 4 )"). arg (x0 ). arg (y0 ). arg (x1 ). arg (y1 );
}
Apater. h
[Html]
# Ifndef APATER_H
# Define APATER_H
# Include "apatee. h"
Class Apater: public Apatee
{
Public:
Apater (Apatee adaptee );
Private:
Apatee apatee;
Public:
Void draw_dot (int x, int y );
};
# Endif // APATER_H
# Ifndef APATER_H
# Define APATER_H
# Include "apatee. h"
Class Apater: public Apatee
{
Public:
Apater (Apatee adaptee );
Private:
Apatee apatee;
Public:
Void draw_dot (int x, int y );
};
# Endif // APATER_H
Apater. cpp
[Html]
# Include <QDebug>
# Include "apater. h"
Apater: Apater (Apatee adaptee)
{
QDebug () <"construct Apater ";
This-> apatee = apatee;
}
Void Apater: draw_dot (int x, int y)
{
QDebug () <(QString ("Apater: draw_dot (int % 1, int % 2)"). arg (x). arg (y ));
Apatee. draw (x, y, x, y );
}
# Include <QDebug>
# Include "apater. h"
Apater: Apater (Apatee adaptee)
{
QDebug () <"construct Apater ";
This-> apatee = apatee;
}
Void Apater: draw_dot (int x, int y)
{
QDebug () <(QString ("Apater: draw_dot (int % 1, int % 2)"). arg (x). arg (y ));
Apatee. draw (x, y, x, y );
}
[Running result]
[Html]
Construct Apatee
Construct Apatee
Construct Apatee
Construct Apater
"Apater: draw_dot (int 1, int 2 )"
"Apatee: draw (int 1, int 2, int 1, int 2 )"
Construct Apatee
Construct Apatee
Construct Apatee
Construct Apater
"Apater: draw_dot (int 1, int 2 )"
"Apatee: draw (int 1, int 2, int 1, int 2 )"
[Analysis]
The adapter mode can also be inherited. After inheriting the Apatee class, the Apater class directly calls the parent class method. Coming soon
[Html]
Apatee. draw (x, y, x, y );
Apatee. draw (x, y, x, y); Replace
[Html] view plaincopyprint? Draw (x, y, x, y );
Draw (x, y, x, y );
[Instance profiling]
In the text code of the Qt Implementation of the MD5 algorithm, the update () function actually applies the idea of the adapter mode.
The update interface we want to implement includes:
[Html]
Private:
Void update (const byte * input, size_t length );
Public:
Void update (const void * input, size_t length );
Void update (const QString & str );
Void update (ifstream & in );
Private:
Void update (const byte * input, size_t length );
Public:
Void update (const void * input, size_t length );
Void update (const QString & str );
Void update (ifstream & in );
But in fact, we only need to implement one interface (this interface is private ):
[Html]
Void update (const byte * input, size_t length );
Void update (const byte * input, size_t length );
Implementation Code
[Html]
Void MD5: update (const byte * input, size_t length)
{
Uint32 I, index, partLen;
_ Finished = false;
/* Compute number of bytes mod 64 */
Index = (uint32) (_ count [0]> 3) & 0x3f); // 0x3f = 63
/* Update number of bits */
If (_ count [0] + = (uint32) length <3) <(uint32) length <3 ))
{
++ _ Count [1];
}
_ Count [1] + = (uint32) length> 29 );
// QDebug () <_ count [0] <_ count [1];
PartLen = 64-index;
/* Transform as same times as possible .*/
If (length> = partLen)
{
Memcpy (& _ buffer [index], input, partLen );
Transform (_ buffer );
For (I = partLen; I + 63 <length; I + = 64)
{
Transform (& input [I]);
}
Index = 0;
}
Else
{
I = 0;
}
/* Buffer remaining input */
Memcpy (& _ buffer [index], & input [I], length-I );
}
/*
MD5 finalization. Ends an MD5 message-_ digest operation, writing
The message _ digest and zeroizing the context.
*/
Void MD5: final ()
{
Byte bits [8];
Uint32 oldState [4];
Uint32 oldCount [2];
Uint32 index, padLen;
/* Save current state and count .*/
Memcpy (oldState, _ state, 16 );
Memcpy (oldCount, _ count, 8 );
/* Save number of bits */
Encode (_ count, bits, 8 );
/* Pad out to 56 mod 64 .*/
Index = (uint32) (_ count [0]> 3) & 0x3f );
PadLen = (index <56 )? (56-index): (120-index );
Update (PADDING, padLen );
/* Append length (before padding )*/
Update (bits, 8 );
/* Store state in digest */
Encode (_ state, _ digest, 16 );
/* Restore current state and count .*/
Memcpy (_ state, oldState, 16 );
Memcpy (_ count, oldCount, 8 );
}
Void MD5: update (const byte * input, size_t length)
{
Uint32 I, index, partLen;
_ Finished = false;
/* Compute number of bytes mod 64 */
Index = (uint32) (_ count [0]> 3) & 0x3f); // 0x3f = 63
/* Update number of bits */
If (_ count [0] + = (uint32) length <3) <(uint32) length <3 ))
{
++ _ Count [1];
}
_ Count [1] + = (uint32) length> 29 );
// QDebug () <_ count [0] <_ count [1];
PartLen = 64-index;
/* Transform as same times as possible .*/
If (length> = partLen)
{
Memcpy (& _ buffer [index], input, partLen );
Transform (_ buffer );
For (I = partLen; I + 63 <length; I + = 64)
{
Transform (& input [I]);
}
Index = 0;
}
Else
{
I = 0;
}
/* Buffer remaining input */
Memcpy (& _ buffer [index], & input [I], length-I );
}
/*
MD5 finalization. Ends an MD5 message-_ digest operation, writing
The message _ digest and zeroizing the context.
*/
Void MD5: final ()
{
Byte bits [8];
Uint32 oldState [4];
Uint32 oldCount [2];
Uint32 index, padLen;
/* Save current state and count .*/
Memcpy (oldState, _ state, 16 );
Memcpy (oldCount, _ count, 8 );
/* Save number of bits */
Encode (_ count, bits, 8 );
/* Pad out to 56 mod 64 .*/
Index = (uint32) (_ count [0]> 3) & 0x3f );
PadLen = (index <56 )? (56-index): (120-index );
Update (PADDING, padLen );
/* Append length (before padding )*/
Update (bits, 8 );
/* Store state in digest */
Encode (_ state, _ digest, 16 );
/* Restore current state and count .*/
Memcpy (_ state, oldState, 16 );
Memcpy (_ count, oldCount, 8 );
}
You can use the adapter mode for other interfaces (public interfaces.
[Html]
Void MD5: update (const void * input, size_t length)
{
Update (const byte *) input, length );
}
Void MD5: update (const QString & str)
{
Update (const byte *) str. toLatin1 (). data (), str. length ());
}
Void MD5: update (ifstream & in)
{
If (! In)
{
Return;
}
Std: streamsize length;
Char buffer [BUFFER_SIZE];
While (! In. eof ())
{
In. read (buffer, BUFFER_SIZE );
Length = in. gcount ();
If (length> 0)
{
Update (buffer, length );
}
}
In. close ();
}
Void MD5: update (const void * input, size_t length)
{
Update (const byte *) input, length );
}
Void MD5: update (const QString & str)
{
Update (const byte *) str. toLatin1 (). data (), str. length ());
}
Void MD5: update (ifstream & in)
{
If (! In)
{
Return;
}
Std: streamsize length;
Char buffer [BUFFER_SIZE];
While (! In. eof ())
{
In. read (buffer, BUFFER_SIZE );
Length = in. gcount ();
If (length> 0)
{
Update (buffer, length );
}
}
In. close ();
}
* The instance is not in the standard adapter mode as in the sample code. Of course it can be rewritten, but I don't think it is necessary. The original intention of the design pattern is to make the code more beautiful and efficient.
Author: tandesir