1.Introduce


在生活中,我们提到适配器可能经常会想到电源适配器或者转换器。国内的充电器一般是220V的长方形两孔插头,当我们出国旅游时,常常发现国内的充电器可能电压或者插孔跟国外的不匹配,导致我们无法正常给自己的手机或者其他电子设备充电,所以在出国之前,大家都会先买个适配当地电源的转换器(适配器)。

而在编码的过程中,我们也有可能会遇到这样一种情况:客户提出了一个需求,我们的系统的数据和行为都能正确的满足客户需求,但是接口不符,这时我们也应该想到为客户打造一个适配器。在设计模式中,有一种叫做适配器模式的方案。其结构如下:

适配器vlan 适配器图片_迭代器

当Adapter类中实现Target接口的方法时,要调用内部引用的Adaptee类,因为我们的目的就是为了使用Adaptee类的功能,给Cilent使用。STL的适配器就是该模式的典型应用案例。STL中的适配器一共分为三类:

  1. 容器适配器
  2. 迭代器适配器
  3. 算法适配器

2.容器适配器


STL中的容器适配器,其就是将不适用的序列式容器(包括 vector、deque 和 list)变得适用。其主要包含下面三类:

适配器vlan 适配器图片_适配器vlan_02


注意:stl中优先队列是基于vector和deque实现的,是因为这两种容器支持随机存取迭代。而list不支持随机存取迭代,故其不是priority_queue的基础容器。

下面我们举两个例子来看看如何初始化容器适配器

std::stack<int> myStack1;  //创建一个不包含任何元素的 stack 适配器,并采用默认的 deque 基础容器
std::stack<int, std::vector<int> > myStack2;  // 使用vector为底层容器的栈

std::queue<int> myQueue1;
std::queue<int, std::list<int>> myQueue2; // 定义以list为底层容器的队列

3.迭代器适配器


我们知道STL 标准库中的容器,无论是序列式容器还是关联式容器(包括哈希容器),要想遍历容器中存储的数据,就只能用使用该容器模板类中提供的迭代器。标准库中迭代器大致分为 5 种类型,分别是输入迭代器、输出迭代器、前向迭代器、双向迭代器以及随机访问迭代器。

适配器vlan 适配器图片_适配器vlan_03


上小节可知stack\queue等是容器适配器,所以其不支持迭代器

适配器vlan 适配器图片_迭代器_04


迭代器适配器,其本质也是一个模板类,其是基于上面5 种基础迭代器实现的。其通过对5 种基础迭代器拥有的成员方法进行整合、修改,甚至为了实现某些功能还会添加一些新的成员方法而实现所需求的功能。

适配器vlan 适配器图片_迭代器_05


下面我们举个例子来看看如使用迭代器适配器

#include <iostream>
#include <list>
using namespace std;
int main()
{
    std::list<int> myList{1,2,3,4,5,6,7,8,9};
    //运用基础迭代器反序变量容器
    std::list<int>::iterator itBegin = myList.end();
    std::list<int>::iterator itEnd = myList.begin();
    //开始遍历
    while (itBegin != itEnd)
    {
        cout << *itBegin << " ";
        --itBegin;
    }
    cout<<endl;
//-----------------------------------------------//
	//运用反向迭代器迭代器遍历
    std::reverse_iterator<std::list<int>::iterator> re_itBegin = myList.rbegin();
    std::reverse_iterator<std::list<int>::iterator> re_itEnd = myList.rend();
    while (re_itBegin != re_itEnd) {
        cout << *re_itBegin << " ";
        //注意,这里是 ++,因为反向迭代器内部互换了 ++ 和 -- 的含义
        ++re_itBegin;
    }
    return 0;
}

4.算法迭代器


算法适配器的作用就是就是将一个函数对象,转换成另一种符合要求的函数对象。在STL中有如下几种算法适配器

适配器vlan 适配器图片_stl_06


下面我们举个例子来看看如使用函数适配器:

在STL中,greater的函数元素如下,其返回的是个bool值,且入参都需要我们输入

template <class T> struct greater {
  bool operator() (const T& x, const T& y) const {return x>y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef bool result_type;
};

现在我们遇到一种情况,找到数组中是否有比50大成员,我们可以应用函数适配器改造greater()函数来达到我们的需求

#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>

using namespace std;

int main()
{
	int intArr[] = {10,20,70,40,50,60,70,80,100};
	const int N = sizeof(intArr) / sizeof(int);
	vector<int>myVector(intArr, intArr + N);
	vector<int>::iterator vecIterator = find_if(myVector.begin(), myVector.end(), bind2nd(greater<int>(), 50));
	if (vecIterator == myVector.end())
		cout << "there are not element greater than 50" << endl;
	else
		cout << "there are element greater than 50, and the first element greater than 50 is:" << *vecIterator << endl;
	system("pause");
	return 0;
}