草稿

适配器模式是软件开发中常用的模式之一,比如我们之前写的类提供的接口(老的接口)在新的环境下已经不合适了,那么我们怎么改变才能使老的接口适配现在新的接口呢?之前说过设计模式中常用的手法就是组合和继承,这在适配器模式中得到了很好的体现。首先,我们要从新的接口继承一个类,这个类就是适配器类(为什么要从新接口继承?那是为了遵循新接口提供的接口规范),那这个适配器类要怎么去适配老的接口呢?很显然的办法是用组合,包含一个指向被适配类的引用,

适配器模式的定义:将一个类的接口转换成客户希望的另外一个接口,从而使原本由于接口不兼容而不能一起工作的类可以一起工作。

用现实中的列子来类比,比如我们常见的电源适配器,就是将原来的接口(不合适的电压),转换成现在可用的接口(

      UML类图

上图是适配器模式的第一种实现形式,适配器Adapter继承自Target和Adaptee类,Adapter类需要重写Target类的Request函数,在Request中做适当的处理,调用Adaptee类的SepcificRequest。最终,Target实际调用的是Adaptee的SpecificRequest来完成Request的,完成适配;这种叫做类适配器。

上图是适配器的第二种实现形式,适配器Adapter类继承自Target类,同时,在Adapter类中有一个Adaptee类型的成员变量;Adapter类重写Request函数时,在Request中,使用Adaptee类型的成员变量调用Adaptee的SpecificRequest函数,最终完成适配;这种叫做对象适配器。

类适配器和对象适配器的比较

既然有了类适配器和对象适配器,那么在实际中如何在二者之间做选择呢?

类适配器有以下特点:

1.由于Adapter直接继承自Adaptee类,所以,在Adapter类中可以对Adaptee类的方法进行重定义;

2.如果在Adaptee中添加了一个抽象方法,那么Adapter也要进行相应的改动,这样就带来高耦合;

3.如果Adaptee还有其它子类,而在Adapter中想调用Adaptee其它子类的方法时,使用类适配器是无法做到的。

对象适配器有以下特点:

1.有的时候,你会发现,不是很容易去构造一个Adaptee类型的对象;

2.当Adaptee中添加新的抽象方法时,Adapter类不需要做任何调整,也能正确的进行动作;

3.可以使用多肽的方式在Adapter类中调用Adaptee类子类的方法。

由于对象适配器的耦合度比较低,所以在很多的书中都建议使用对象适配器。在我们实际项目中,也是如此,能使用对象组合的方式,就不使用多继承的方式。

代码实现

类适配器的实现代码

复制代码代码如下:

/*
** FileName     : AdapterPatternDemo
** Author       : Jelly Young
** Date         : 2013/11/27
** Description  : More information, please go to http://www.jellythink.com
*/
 
#include
using namespace std;
 
// Targets
class Target
{
public:
    virtual void Request()
    {
        cout<<“Target::Request”<<endl;
    }
};
 
// Adaptee
class Adaptee
{
public:
    void SpecificRequest()
    {
        cout<<“Adaptee::SpecificRequest”<<endl;
    }
};
 
// Adapter
class Adapter : public Target, Adaptee
{
public:
    void Request()
    {
        Adaptee::SpecificRequest();
    }
};
 
// Client
int main(int argc, char *argv[])
{
    Target *targetObj = new Adapter();
    targetObj->Request();
 
    delete targetObj;
    targetObj = NULL;
 
    return 0;
}
对象适配器的代码实现

复制代码代码如下:

/*
** FileName     : AdapterPatternDemo
** Author       : Jelly Young
** Date         : 2013/11/27
** Description  : More information, please go to http://www.jellythink.com
*/
 
#include
using namespace std;
 
class Target
{
public:
    Target(){}
    virtual ~Target(){}
    virtual void Request()
    {
        cout<<“Target::Request”<<endl;
    }
};
 
class Adaptee
{
public:
    void SpecificRequest()
    {
        cout<<“Adaptee::SpecificRequest”<<endl;
    }
};
 
class Adapter : public Target
{
public:
    Adapter() : m_Adaptee(new Adaptee) {}
 
    ~Adapter()
    {
        if (m_Adaptee != NULL)
        {
            delete m_Adaptee;
            m_Adaptee = NULL;
        }
    }
 
    void Request()
    {
        m_Adaptee->SpecificRequest();
    }
 
private:
    Adaptee *m_Adaptee;
};
 
int main(int argc, char *argv[])
{
    Target *targetObj = new Adapter();
    targetObj->Request();
 
    delete targetObj;
    targetObj = NULL;
 
    return 0;
}
总结 

结合到我们的例子和适配器模式的定义,其中稳定的部分就是目标接口类和源接口类,而变化的是适配器类,因为如果有新的目标接口的话适配器类就做出相应的改变,以适应新的接口。我们通过继承的方式来得到新接口的接口规范(就是要用它的虚函数),然后通过组合的方式(就是包含一个老接口的指针作为适配器类的成员)得到老接口的某些使用方法从而达到适应新接口的目的。

上一篇:为什么使用Python的’-i’或’-c’选项导致之前会话的readline历史记录不可用?


下一篇:13 CSS样式权重问题