适配器模式可以将一个类的接口转换成客户端希望的另一个接口,使得原来由于接口不兼容而不能在一起工作的那些类可以在一起工作。通俗的讲就是当我们已经有了一些类,而这些类不能满足新的需求,此时就可以考虑是否能将现有的类适配成可以满足新需求的类。适配器类需要继承或依赖已有的类,实现想要的目标接口。
缺点:过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
类模式的 Adapter 实现
//目标接口
class Target
{
public:
virtual void Request() = 0;
};
//适配者类
class Adaptee
{
public:
void SpecificRequest()
{
cout << "called SpecificRequest " << endl;
}
};
//适配器类
class Adapter : public Target,private Adaptee
{
public:
void Request()
{
SpecificRequest();
}
};
int main()
{
Target * pTarget = new Adapter();
pTarget->Request();
}
对象模式的 Adapter 实现
class Target
{
public:
virtual void Request() = 0;
};
class Adaptee
{
public:
void SpecificRequest()
{
cout << "call SpecificRequest" << endl;
}
};
class Adapter : public Target
{
private:
Adaptee* m_pAdaptee;
public:
Adapter(Adaptee * pAdaptee)
{
m_pAdaptee = pAdaptee;
}
void Request()
{
m_pAdaptee->SpecificRequest();
}
};
int main()
{
Adaptee * pAdaptee = new Adaptee();
Target * pTarget = new Adapter(pAdaptee);
pTarget->Request();
return 0;
}
举例
在STL中就用到了适配器模式。STL实现了一种数据结构,称为双端队列(deque),支持前后两段的插入与删除。STL实现栈和队列时,没有从头开始定义它们,而是直接使用双端队列实现的。这里双端队列就扮演了适配器的角色。队列用到了它的后端插入,前端删除。而栈用到了它的后端插入,后端删除。假设栈和队列都是一种顺序容器,有两种操作:压入和弹出
class Sequence
{
public:
virtual void push(int x) = 0;
virtual void pop() = 0;
};
class Deque
{
public:
void push_back(int x) { cout << "Deque push_back:" << x << endl; }
void push_front(int x) { cout << "Deque push_front:" << x << endl; }
void pop_back() { cout << "Deque pop_back" << endl; }
void pop_front() { cout << "Deque pop_front" << endl; }
};
//栈 先进后出
class Stack : public Sequence,private Deque
{
public:
void push(int x)
{
push_front(x);
}
void pop()
{
pop_front();
}
};
//队列 先进先出
class Queue : public Sequence,private Deque
{
public:
void push(int x)
{
push_back(x);
}
void pop()
{
pop_front();
}
};
int main()
{
Stack * pStack = new Stack();
Queue * pQueue = new Queue();
pStack->push(1);
pStack->pop();
pQueue->push(1);
pQueue->pop();
return 0;
}
class Sequence
{
public:
virtual void push(int x) = 0;
virtual void pop() = 0;
};
class Deque
{
public:
void push_front(int x) { cout << "Deque push_front:" << x << endl; }
void push_back(int x) { cout << "Deque push_back:" << x << endl; }
void pop_front() { cout << "Deque pop_front" << endl; }
void pop_back() { cout << "Deque pop_back" << endl;}
};
//堆栈 先入后出
class Stack : public Sequence
{
private:
Deque * m_pDeque;
public:
Stack(Deque * pDeque)
{
m_pDeque = pDeque;
}
void push(int x)
{
m_pDeque->push_front(x);
}
void pop()
{
m_pDeque->pop_front();
}
};
class Queue : public Sequence
{
private:
Deque * m_pDeque;
public:
Queue(Deque * pDeque)
{
m_pDeque = pDeque;
}
void push(int x)
{
m_pDeque->push_back(x);
}
void pop()
{
m_pDeque->pop_front();
}
};
int main()
{
Deque * pDeque = new Deque();
Stack * pStack = new Stack(pDeque);
Queue * pQueue = new Queue(pDeque);
pStack->push(1);
pStack->pop();
pQueue->push(1);
pQueue->pop();
return 0;
}