设计模式(6)-适配器模式(Apater)
【描述】适配器模式将某个对象的接口适配为另一个对象所期望的接口。
【UML图】
图1 Apater模式
(1) 已知Apatee类,该类提供了画线的函数实现;
(2) 现在用户要求绘制点,我们知道如果将画线函数起点和终点坐标取一致,实际上就相当于绘制了点。于是决定采用适配器模式将画线函数适配为画点函数。
【代码清单】
apatee.h
#ifndef APATEE_H#define APATEE_Hclass Apatee{public: Apatee();public: void draw(int x0, int y0, int x1, int y1);};#endif // APATEE_H
apatee.cpp
#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
#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
#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);}
【运行结果】
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)"
【分析】
适配器模式实际上,也可采用继承实现。继承Apatee类后,Apater类中直接调用父类方法。即将
apatee.draw(x, y, x, y);
替换为
draw(x, y, x, y);
【实例剖析】
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);
但实际上,我们只需实现一个接口(这个接口是私有的):
void update(const byte* input, size_t length);
实现代码
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 many 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 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 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();}
*所述实例,并不是示例代码中那样标准的适配器模式。当然可以进行改写,但我认为完全没有必要。设计模式的初衷就是使代码更为美观、高效。
【实例下载】
http://download.csdn.net/detail/tandesir/4490759
转载请标明出处,仅供学习交流,勿用于商业目的
Copyright @ http://blog.csdn.net/tandesir