类图
用一个具体的Adapter类对Adaptee和Target进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类Adapter将不能胜任工作。
使得Adapter可以重新定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类。
仅仅引入一个对象,并不需要额外的指针以间接得到Adaptee。
允许一个Adater与多个Adaptee(即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。Adapter也可以一次给所有的Adaptee添加功能。
使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。
定义
将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
- 有时,为复用而设计的工具箱类不能够被复用的原因仅仅是因为它的接口与专业应用领域所需要的接口不匹配(名称不一样,参数不一样等等)
- 我们可以改变工具箱类使它兼容专业领域中的类的接口,但前提是必须有这个工具箱的源代码,然而 即使我们得到了这些源代码,修改工具箱也是没有什么意义的,因为不应该仅仅为了实现一个应用,工具箱就不得不采用一些与特定领域相关的接口。
- 我们可以不用上面的方法,而定义一个适配器类,由他来适配工具箱接口和专业应用的接口。我们可以用两种方法做这件事:
- 继承专业应用类的接口和工具箱类的实现。这种方法对应Adapter模式的类版本(多继承)
- 将工具箱类的实现作为适配器类的组成部分,并且使用工具箱的接口实现适配器类。这种方法对应Adapter模式的对象版本。
优缺点
优点:
缺点:
适用环境:
以下情况使用Adapter模式:
- 你想使用一个已经存在的类,而它的接口不符合你的需求。
- 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
设计原则
代码
Duck类:
#ifndef DUCK_H
#define DUCK_H
#include <QDebug>
class Duck
{
public:
virtual void quack() = 0;
virtual void fly() = 0;
};
#endif // DUCK_H
MallardDuck 类:
#ifndef MALLARDDUCK_H
#define MALLARDDUCK_H
#include "duck.h"
class MallardDuck : public Duck
{
public:
void quack() override;
void fly() override;
};
#endif // MALLARDDUCK_H
#include "mallardduck.h"
void MallardDuck::quack()
{
qDebug() << "Quack";
}
void MallardDuck::fly()
{
qDebug() << "i'm flying";
}
TurkeyAdapter 类:
#ifndef TURKEYADAPTER_H
#define TURKEYADAPTER_H
#include "duck.h"
#include "Turkry.h"
class TurkeyAdapter : public Duck
{
public:
TurkeyAdapter(Turkey *turkey);
void quack() override;
void fly() override;
private:
Turkey *turkey;
};
#endif // TURKEYADAPTER_H
#include "turkeyadapter.h"
TurkeyAdapter::TurkeyAdapter(Turkey *turkey)
{
this->turkey = turkey;
}
void TurkeyAdapter::quack()
{
turkey->gobble();
}
void TurkeyAdapter::fly()
{
for(int i = 0; i < 5; i++) {
turkey->fly();
}
}
Turkey类:
#ifndef TURKRY_H
#define TURKRY_H
#include <QDebug>
class Turkey
{
public:
virtual void gobble() = 0;
virtual void fly() = 0;
};
#endif // TURKRY_H
WildTurkey类:
#ifndef WILDTURKEY_H
#define WILDTURKEY_H
#include "Turkry.h"
class WildTurkey : public Turkey
{
public:
void gobble() override;
void fly() override;
};
#endif // WILDTURKEY_H
#include "wildturkey.h"
void WildTurkey::gobble()
{
qDebug() << "Gobble gobble";
}
void WildTurkey::fly()
{
qDebug() << "i'm flying a short distance;";
}
测试:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "duck.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
void testDuck(Duck *duck);
~MainWindow();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "mallardduck.h"
#include "wildturkey.h"
#include "turkeyadapter.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
MallardDuck *duck = new MallardDuck();
WildTurkey *turkey = new WildTurkey();
Duck *turkeyAdapter = new TurkeyAdapter(turkey);
qDebug() << "The Turkey says...";
turkey->gobble();
turkey->fly();
qDebug() << "The Duck says...";
testDuck(duck);
qDebug() << "The TurkeyAdapter says...";
testDuck(turkeyAdapter);
}
MainWindow::~MainWindow()
{
}
void MainWindow::testDuck(Duck *duck)
{
duck->quack();
duck->fly();
}