适配器模式(adapter)
适配器模式
1 作用
名字很形象的说出了模式的作用:当有一个需求需要Target的接口,然后有一个现成的Adaptee接口,为了让Adaptee接口匹配上Target接口,就需要使用Adapter,在Adapter中将Adaptee适配Target。
Adapter和Bridge模式都使用了关联关系,Bridge中关联的两个类都可以扩展,Adapter中只会扩展Target产生新的Adapter,Adatee是固定不修改了。
2 实现方式
实现Adapter适配器设计模式有两种方式:组合(compositon, has-a关系)和继承(inheritance,is-a关系)。
对象适配器模式使用组合,UML图如下:
就是Aapter里实际上包含一个被适配的对象。(组合)又继承了target。因此如果要用到target的方法,直接调用父类的方法,如果要用到被适配者的方法, 就调用内部成员的函数。
3 C++代码
STL里的stack和queue都是adapter,底层是deque,隐藏了deque的一些接口,使得其可以达到FIFO是queue,LIFO是stack。
下面用适配器模式模拟将deque生成queue和stack接口。
SequentialContainer.h
#include <deque>
#ifndef __QUEUE__H__
#define __QUEUE__H__
template<typename T>
class SequentialContainer {
public:
SequentialContainer() = default;
virtual ~SequentialContainer() {} // 虚析构函数
virtual void put(const T &v) = 0;
virtual T pop() = 0;
};
template<typename T>
class Stack:public SequentialContainer<T> {
public:
Stack(std::deque<T> *dq):dq(dq){}
~Stack() { delete dq; } // 析构指针对象指向的空间
void put(const T &v) override { dq->emplace_front(v);}
T pop() override {
if(dq->size()>0){
int tmp = dq->front();
dq->pop_front();
return tmp;
} else {
return 0;
}
}
private:
std::deque<T> *dq;
};
template<typename T>
class Queue:public SequentialContainer<T> {
public:
Queue(std::deque<T> *dq):dq(dq){}
~Queue() { delete dq; } // 析构指针对象指向的空间
void put(const T &v) override { dq->emplace_front(v);}
T pop() override {
int tmp = dq->back();
dq->pop_back();
return tmp;
}
private:
std::deque<T> *dq;
};
#endif
test.h
#include <iosteam>
#include <deque>
#include "SequntialContainer.h"
using namespace std;
int main() {
SequentialContainer<int> *stack = new Stack<int>(new deque<int>);
SequentialContainer<int> *queue = new Queue<int>(new deque<int>);
for(int i=0; i<10; ++i){
stack->put(i);
queue->put(i);
}
cout<<"stack output:";
for(int i=0; i<11; ++i)
cout<<stack->pop()<<" ";
cout<<endl;
cout<<"fifo output:";
for(int i=0; i<11; ++i)
cout<<queue->pop()<<" ";
cout<<endl;
delete stack; // 析构动态生成的对象
delete queue;
return 0;
}
输出:
超出队列或者stack的长度后,输出都是0.
Adpter中不保存Adaptee的指针,而是对象,这样就不要析构函数了。
SequentialContainer.h
#include <deque>
#ifndef __QUEUE__H__
#define __QUEUE__H__
template<typename T>
class SequentialContainer {
public:
SequentialContainer() = default;
virtual ~SequentialContainer(){} // 虚析构函数
virtual void put(const T &v) = 0;
virtual T pop() = 0;
};
template<typename T>
class Stack:public SequentialContainer<T> {
public:
Stack(std::deque<T> dq):dq(dq){}
void put(const T &v) override { dq.emplace_front(v);}
T pop() override {
if(dq.size()>0){
int tmp = dq.front();
dq.pop_front();
return tmp;
} else {
return 0;
}
}
private:
std::deque<T> dq;
};
template<typename T>
class Queue:public SequentialContainer<T> {
public:
Queue(std::deque<T> dq):dq(dq){}
void put(const T &v) override { dq.emplace_front(v);}
T pop() override {
int tmp = dq.back();
dq.pop_back();
return tmp;
}
private:
std::deque<T> dq;
};
#endif
test.cc
#include <iostream>
#include "SequentialContainer.h"
using namespace std;
int main() {
SequentialContainer<int> *stack = new Stack<int>(deque<int>());
SequentialContainer<int> *queue = new Queue<int>(deque<int>());
for(int i=0; i<10; ++i){
stack->put(i);
queue->put(i);
}
cout<<"stack output:";
for(int i=0; i<11; ++i)
cout<<stack->pop()<<" ";
cout<<endl;
cout<<"queue output:";
for(int i=0; i<11; ++i)
cout<<queue->pop()<<" ";
cout<<endl;
delete stack; // 析构动态生成的对象
delete queue;
return 0;
}