适配器模式

在STL中,很多地方都用到了适配器,包括容器适配器,迭代器适配器,函数适配器

适配器模式的定义为:将一个类的接口转换为另一个类的接口,使原本因接口不兼容而不能工作的类可以一起工作

适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

优点

  • 客户端通过适配器可以透明地调用目标接口。
  • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
  • 在很多业务场景中符合开闭原则。

缺点

  • 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
  • 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。

应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

适配器的实现

适配器模式(Adapter)包含以下主要角色。

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

类适配器实现

类适配器模式可采用多重继承方式实现,如 C++ 可定义一个适配器类来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口。

Java不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

class_adapter
class_adapter

对象适配器实现

对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口

object_adapter
object_adapter

容器适配器

在STL中有三种容器适配器,这里不过多介绍

迭代器适配器

  • reverse_iterator: 逆序遍历的迭代器适配器(类模板)
  • make_reverse_iterator(C++14): 创建拥有从实参推出的类型的 std::reverse_iterator(函数模板)
  • move_iterator(C++11): 解引用结果为右值引用的迭代器适配器(类模板)
  • make_move_iterator(C++11): 创建拥有从实参推出的类型的 std::move_iterator(函数模板)
  • back_insert_iterator: 用于在容器尾部插入的迭代器适配器(类模板)
  • back_inserter: 创建拥有从实参推出的类型的 std::back_insert_iterator(函数模板)
  • front_insert_iterator: 用于在容器头部插入的迭代器适配器(类模板)
  • front_inserter: 创建拥有从实参推出的类型的 std::front_insert_iterator(函数模板)
  • insert_iterator: 用于插入容器的迭代器适配器(类模板)
  • inserter: 创建拥有从实参推出的类型的 std::insert_iterator(函数模板)

如ReverseIterator的实现,将++操作换成迭代器的–操作,实现逆向遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
template <typename Iterator>
class ReverseIterator {
public:
using iterator_type = Iterator;
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
using value_type = typename std::iterator_traits<Iterator>::value_type;
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
using pointer = typename std::iterator_traits<Iterator>::pointer;
using reference = typename std::iterator_traits<Iterator>::reference;

ReverseIterator() : it_() {}
ReverseIterator(iterator_type it) : it_(it) {}
template <typename It>
ReverseIterator(const ReverseIterator<It>& other) : it_(other.it_) {}

template <typename It>
ReverseIterator& operator=(const ReverseIterator<It>& other) {
it_ = other.it_;
}

iterator_type base() const { return it_; }

reference operator*() {
return *gtl::prev(it_);
}
pointer operator->() { return gtl::addressof(**this); }
reference operator[](difference_type n) { return *gtl::prev(n + 1); }

ReverseIterator& operator++() {
--it_;
return *this;
}
ReverseIterator operator++(int) {
auto ret = *this;
--it_;
return ret;
}
ReverseIterator& operator--() {
++it_;
return *this;
}
ReverseIterator operator--(int) {
auto ret = *this;
++it_;
return ret;
}
ReverseIterator& operator+=(difference_type n) {
it_ -= n;
return *this;
}
ReverseIterator& operator-=(difference_type n) {
it_ += n;
return *this;
}
ReverseIterator operator+(difference_type n) const { return ReverseIterator(it_ - n); }
ReverseIterator operator-(difference_type n) const { return ReverseIterator(it_ + n); }

template <typename It>
friend bool operator==(const ReverseIterator<It>& lhs, const ReverseIterator<It>& rhs);
template <typename It>
friend bool operator<(const ReverseIterator<It>& lhs, const ReverseIterator<It>& rhs);

private:
iterator_type it_;
};

函数适配器

早期的C++提供了一些函数适配器,如bind1st和bind2nd(C++11后可用bind替代)

早期提供功能支持的几个工具在C++11中弃用,并于 C++17 中移除(旧否定器于 C++17 中弃用并于 C++20 中移除),这里不再过多介绍

参考