欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计模式-适配器模式(Apater)

程序员文章站 2022-06-23 15:43:36
【描述】适配器模式将某个对象的接口适配为另一个对象所期望的接口。 【uml图】   图1 apater模式 (1) 已知apatee类,该类提供了画线的函数实现; (2) 现在用户要求绘制...

【描述】适配器模式将某个对象的接口适配为另一个对象所期望的接口。

【uml图】

 设计模式-适配器模式(Apater)

图1 apater模式

(1) 已知apatee类,该类提供了画线的函数实现;

(2) 现在用户要求绘制点,我们知道如果将画线函数起点和终点坐标取一致,实际上就相当于绘制了点。于是决定采用适配器模式将画线函数适配为画点函数。

 

【代码清单】

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);
}

【运行结果】

[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)"  

【分析】
适配器模式实际上,也可采用继承实现。继承apatee类后,apater类中直接调用父类方法。即将

[html]
apatee.draw(x, y, x, y); 

apatee.draw(x, y, x, y);替换为

[html] view plaincopyprint?draw(x, y, x, y); 

draw(x, y, x, y);
【实例剖析】

md5算法的qt实现一文代码中,update()函数实际上就是应用了适配器模式的思想。

我们要实现的update接口包括:

[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);

但实际上,我们只需实现一个接口(这个接口是私有的):

[html]
void update(const byte* input, size_t length); 

void update(const byte* input, size_t length);
实现代码

[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 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 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);
}
其余接口(公有的)采用适配器模式就可以了。

[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();
}
*所述实例,并不是示例代码中那样标准的适配器模式。当然可以进行改写,但我认为完全没有必要。设计模式的初衷就是使代码更为美观、高效。

 作者:tandesir