定义
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
要点
1)当需要使用一个现有的类而其接口并不符合你的需要时,就使用适配器。
2)适配器改变接口以符合客户的期望。
3)适配器有两种形式:对象适配器和类适配器。类适配器需要多重继承,故推荐使用对象适配器。
4)适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;外观将一群对象“包装”起来以简化其接口。
5)适配器允许客户使用新的库和子集合,无需改变“任何”代码。
6)适配器可以适配多个类来提供一个接口,即可以有多个被适配者。
客户使用适配器的过程
1.客户通过目标接口调用适配器的方法对适配器发出请求。
2.适配器使用被适配者接口把请求转换成被适配者的一个或多个调用接口。
3.客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用。
类图
Target:目标接口。
Adapter:适配器,实现目标接口,同时组合被适配者。这样被适配者的任何子类都可以搭配着适配器使用。
Adaptee:被适配者。
示例
下面实现一个火鸡适配器。通过调用鸭子的方法能够调用到火鸡的方法。
Duck.h
#ifndef DUCK_H
#define DUCK_H
#include <iostream>
#include <string>
namespace adapter {
using std::string;
using std::cout;
using std::endl;
// 鸭子接口
class Duck
{
public:
Duck(){}
virtual ~Duck(){}
virtual void quack() = 0;
virtual void fly() = 0;
};
class RedDuck: public Duck
{
public:
RedDuck(string n = "Red duck"): name(n)
{
}
~RedDuck(){}
void quack()
{
cout << name << " is quacking" << endl;
}
void fly()
{
cout << name << " is flying" << endl;
}
private:
string name;
};
}
#endif
Turkey.h
#ifndef TURKEY_H
#define TURKEY_H
#include <iostream>
#include <string>
namespace adapter {
using std::string;
using std::cout;
using std::endl;
// 火鸡接口
class Turkey
{
public:
Turkey(){}
virtual ~Turkey(){}
virtual void gobble() = 0;
virtual void fly() = 0;
};
class WildTurkey: public Turkey
{
public:
WildTurkey(string n): name(n)
{
}
~WildTurkey(){}
void gobble()
{
cout << name << " is goobling" << endl;
}
void fly()
{
cout << name << " is flying" << endl;
}
private:
string name;
};
}
#endif
TurkeyAdapter.h
#ifndef TURKEY_ADAPTER_H
#define TURKEY_ADAPTER_H
#include "Duck.h"
#include "Turkey.h"
namespace adapter {
// 火鸡适配器
class TurkeyAdapter: public Duck
{
public:
TurkeyAdapter(Turkey *t): turkey(t)
{}
~TurkeyAdapter(){}
void quack()
{
turkey->gobble();
}
void fly()
{
turkey->fly();
}
private:
Turkey *turkey;
};
}
#endif
main.cpp
#include "Duck.h"
#include "Turkey.h"
#include "TurkeyAdapter.h"
using namespace adapter;
int main()
{
Turkey *wt = new WildTurkey("James");
TurkeyAdapter *ta = new TurkeyAdapter(wt);
ta->fly();
ta->quack();
delete ta;
delete wt;
return 0;
}
Makefile
CXX = g++
CFLAGS = -Wall
LDFLAGS =
target = res
srcs = main.cpp
objs = $(srcs:.cpp=.o)
headers = $(wildcard *.h)
.PHONY: all
all: $(target)
$(target): $(objs) $(headers)
$(CXX) $(LDFLAGS) -o $(target) $(objs)
$(objs):%.o:%.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(target) *.o
测试
测试结果如下所示: