C++实现Structural - Adapter模式

Adapter模式也称为Wrapper模式。

 

在软件系统中,由于应用环境的变化,常常需要将一些现存的对象放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。Adapter设计模式就是为了应对这种迁移的变化,以使客户系统既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口。

 

事实上,Adapter设计模式的意图是:

“Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.” ---GoF

 

Adapter模式有两种形式:

1. 对象适配器。其UML类图如下:

在对象适配器形式下,Adapter类中需要拥有一个Adaptee对象adaptee,然后通过该对象调用Adaptee类中的specific_request函数。

 

2. 类适配器。其UML类图如下:

   在类适配器形式下,类Adapter通过继承类Adaptee的方式,从而可以获取specific_request函数的访问权。

 

通常情况下使用的是对象适配器。原因是:

1. 类适配器使用多重继承,但JavaC#不像C++那样支持多重继承(JavaC#可以实现多个接口,但只能继承一个父类)

如果一个适配器要适配两个已经存在的类,用类适配器的方式是不可能实现的。

2. 在图2Adapter由于实现了IRequest接口的同时继承了Adaptee类,因此它不仅提供了接口IRequest中的方法Request

同时也提供了Adaptee中的SpecificRequest方法,这样就使得Adapter的功能不够单一,从而造成混乱。由此产生了一种

说法:包含优于继承

 

   一般性原则:在面向对象编程的时候,方法或者函数的参数最好是接口或者抽象类。

 

举例:

STL中的顺序容器适配器stackqueuepriority_queue都是采用Adapter模式实现的。顺带说明一下,stackqueue的底层容器缺省地是dequepriority_queue的底层容器缺省地是vector。实际上,我们可以改变stackqueuepriority_queue这些适配器的底层容器,比如:

stack< string, vector<string> > str_stk;

那么此时str_stk这个stack,通过增加了第2个模板参数,使得其底层容器就变成了vector

 

stack的底层容器可以是:vectordequelist

queue的底层容器可以是:dequelist

priority_queue的底层容器可以是:vectordeque

 

下面我们用对象适配器和类适配器的形式,来模拟实现STL中的stack。更具STL的文档,我们知道一个stack包含以下操作:

s.empty()           如果s中没有元素,则返回true,否则返回false

s.size()               返回s中元素的个数

s.pop                  删除栈顶元素,但不返回任何值

s.top()                返回栈顶元素,但不删除它

s.push(item)     压栈,即将一个元素item放在栈顶的位置。

 

很显然,这些操作比如popvector容器中是不存在的,但由于我们的客户代码希望有这样的操作,因此我们需要构建一个适配器Stack(S为大写,以示和STL::stack有所区别),对象适配器形式的Adapter代码如下:

// Adapter.h

#include <iostream>

#include <vector>

#include <string>

using namespace std;

 

// 这个类用作容器中的元素

class Person

{

private:

         string name;

         int age;

public:

         void set_name(const string& name)

         {

                   this->name = name;

         }

 

         string get_name() const

         {

                   return name;

         }

 

         void set_age(const int& age)

         {

                   this->age = age;

         }

 

         int get_age() const

         {

                   return age;

         }

};

 

// 接口类

template<typename T>

class Stack

{

public:

         virtual bool empty() const = 0;

         virtual size_t size() const = 0;

         virtual void pop() = 0;

         virtual T& top() = 0;

         virtual void push(const T&) = 0;

 

public:

         virtual ~Stack()

         {

                   cout << "in the destructor of Stack..." << endl;

         }

};

 

// 实现Adapter

template<typename T>

class Adapter : public Stack<T>

{

private:

         vector<T> v;

public:

         bool empty() const

         {

                   return v.empty();

         }

 

         size_t size() const

         {

                   return v.size();

         }

 

         void pop()

         {

                   v.pop_back();

         }

 

         T& top()

         {

                   return v[v.size() - 1];

         }

 

         void push(const T& x)

         {

                   v.push_back(x);

         }

};

 

// 客户端调用代码:Adapter.cpp

#include "Adapter.h"

 

int main(int argc, char **argv)

{

         Stack<Person> *stk = new Adapter<Person>;

 

         Person p1;

         p1.set_name("玄机逸士");

         p1.set_age(28);

 

         Person p2;

         p2.set_name("飘渺仙子");

         p2.set_age(18);

 

         Person p3;

         p3.set_name("上官天野");

         p3.set_age(27);

 

         Person p4;

         p4.set_name("孟神通幽");

         p4.set_age(30);

 

         stk->push(p1);

         stk->push(p2);

         stk->push(p3);

         stk->push(p4);

 

         cout << "size = " << stk->size() << endl;

         cout << "-----------------------------" << endl;

 

         cout << (stk->top()).get_name() << ",\t" << (stk->top()).get_age() << endl;

         stk->pop();

 

         cout << (stk->top()).get_name() << ",\t" << (stk->top()).get_age() << endl;

         stk->pop();

 

         cout << (stk->top()).get_name() << ",\t" << (stk->top()).get_age() << endl;

         stk->pop();

 

         cout << (stk->top()).get_name() << ",\t" << (stk->top()).get_age() << endl;

         stk->pop();

 

         cout << "-----------------------------" << endl;

         if(stk->empty())

         {

                   cout << "The stack is empty..." << endl;

         }

         else

         {

                   cout << "The stack is not empty..." << endl;

         }

 

         return 0;

}

运行结果:

size = 4

-----------------------------

孟神通幽,  30

上官天野,  27

飘渺仙子,  18

玄机逸士,  28

-----------------------------

The stack is empty...

 

各类和对象适配器UML类图中的各类之间的对应关系:

Stack                  < ------ >             IRequest

Adapter              < ------ >             Adapter

vector                 < ------ >             Adaptee

main函数          < ------ >             PatternClient

 

 

类适配器形式的实现代码和上面的非常相似,略。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值