适配器模式
UML类图:
1、接口继承与实现继承
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。
接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承,
子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)
。在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以
对外提供父类中的接口操作,又可以获得父类的接口实现。当然我们可以通过一定的方式
和技术模拟单独的接口继承和实现继承,例如我们可以通过private继承获得实现继承的
效果(private继承后,父类中的接口都变为private,当然只能是实现继承了。)
,通过纯抽象基类模拟接口继承的效果,但是在C++中pure virtual function
也可以提供默认实现,因此这是不纯正的接口继承,但是在Java中我们可以interface
来获得真正的接口继承了。
2. 主要缺点
类适配器模式的缺点如下:
(1) 对于Java、C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者;(适
配多个类时使用多继承)
(2) 适配者类不能为最终类,如在Java中不能为final类,C#中不能为sealed类;
(3) 在Java、C#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。
对象适配器模式的缺点如下:
与类适配器模式相比,要在适配器中置换适配者类的某些方法比较麻烦。如果一定要置换掉适配者类的一个或多个方法,可以先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
3. 适用场景
在以下情况下可以考虑使用适配器模式:
(1) 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
(2) 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
#pragma once
#ifndef _ADAPTER_H
#define _ADAPTER_H
#include<string>
#include<cassert>
//目标类(客户端需要使用的类)
class Target
{
public:
Target()
{}
~Target()
{}
virtual void Request()//定义标准接口
{
puts("Request");
}
};
//需要适配的类
class Adaptee
{
public:
Adaptee()
{}
~Adaptee()
{}
void SpecialRequest()
{
puts("SpecialRequest");
}
};
//类适配器(只适用于多继承) 私有继承需要被适配的类
class Adapter :public Target, private Adaptee
{
public:
Adapter()
{}
~Adapter()
{}
void Request()
{
SpecialRequest();
}
};
//对象适配器
class AdapterObject :public Target
{
public:
AdapterObject(Adaptee* pAd)
{
m_pAd = pAd;
}
~AdapterObject()
{
}
void Request()
{
m_pAd->SpecialRequest();
}
private:
Adaptee* m_pAd;
};
#endif
#include<iostream>
#include"Adapter.h"
using namespace std;
int main(void)
{
//类适配器
Adaptee* ade = new Adaptee();
//对象适配器
Target* adt = new AdapterObject(ade);
adt->Request();
puts("---------------");
delete ade;
delete adt;
adt = new Target();
adt->Request();
delete adt;
return 0;
}