程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 設計模式(6)-適配器模式(Apater)

設計模式(6)-適配器模式(Apater)

編輯:C++入門知識

【描述】適配器模式將某個對象的接口適配為另一個對象所期望的接口。

【UML圖】

 \

圖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] view plaincopyprint?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] view plaincopyprint?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();
}
*所述實例,並不是示例代碼中那樣標准的適配器模式。當然可以進行改寫,但我認為完全沒有必要。設計模式的初衷就是使代碼更為美觀、高效。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved