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