疑问:
- 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。 如何应对这种“迁移的变化”?
- 如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?
定义:
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
——《设计模式》GoF
一、对象适配器
对象适配器采用对象组合,通过引用一个类与另一个类接口 在对象适配器中通过组合获得Adaptee对象 通过调用Adaptee对象的方法,转换后返回Target结果。
二、类适配器
类适配器通过多继承对一个接口与另一个接口进行匹配。
Target定义了Client使用的与特定领域相关的接口,Client通过调用Target实现某一个特定的操作。Adaptee是一个已经存在的类,需要与Target协同工作,这个接口需要适配。Adapter适配器适配Adaptee和Target接口。在类适配器中,通过继承获得Adaptee中的方法。
.NET不支持多重继承,因此当Target是一个类,而不是一个接口时无法实现类适配器,这时需要使用对象适配器。
三、生活中的例子
在国内使用的电源供电电压为220V,美国为380V,当你出差到美国,你的电器需要220V的电压,但旅馆里不提供220V,只提供380,所以,你到市场买了一个电源适配器,在接上适配器后,旅馆里的电源就可以使用在你的电器上了。
Target:标准电源
Adaptee:美国电源
Adapter:适配器
1、实现-Target
/// <summary>
/// 目标:Target
/// </summary>
public class StandardPower
{
/// <summary>
/// 供电
/// </summary>
/// <returns></returns>
public virtual int SupplyPower()
{
Console.Write("正常SupplyPower,电压:");
return 220;
}
}
2、实现-Adaptee
/// <summary>
/// 要适配的对象:Adaptee
/// </summary>
public class AmericanPower
{
public int SupplyPower()
{
Console.Write("在美国供给380V电压");
return 380;
}
}
3、实现-Adapter
/// <summary>
/// 适配器:Adapter
/// </summary>
public class PowerAdapter : StandardPower
{
/// <summary>
/// 当地电源
/// </summary>
private AmericanPower localPower = new AmericanPower();
public override int SupplyPower()
{
int v = localPower.SupplyPower();
if (v != 220)
{
//这里做一些转换工作
v = 220;
}
Console.WriteLine("转换后的电压:{0}", v.ToString());
return v;//转换后,即适配后
}
}
4、实现-使用
StandardPower power = null;
//在中国的时候
power = new StandardPower();
Console.WriteLine(power.SupplyPower());
//到美国以后,买一个适配器
power = new PowerAdapter();
Console.WriteLine("适配后提SupplyPower源电压为:{0}", power.SupplyPower());
//让控制台 等待
Console.ReadLine();
四、.NET中的Adapter模式
1.适配器模式在.NET Framework中的一个最大的应用就是COM Interop。
COM Interop就好像是COM和.NET之间的一座桥梁(关于COM互操作更多内容可以参考我的互操作系列)。COM组件对象与.NET类对象是完全不同的,但为了使.NET程序
象使用.NET对象一样使用COM组件,微软在处理方式上采用了Adapter模式,对COM对象进行包装,这个包装类就是RCW(Runtime Callable Wrapper)。RCW实际上是runtime生成的一个.NET类,它包装了COM组件的方法,并内部实现对COM组件的调用。如下图所示:
2..NET中的另外一个适配器模式的应用就是DataAdapter。
ADO.NET为统一的数据访问提供了多个接口和基类,其中最重要的接口之一是IdataAdapter。DataAdpter起到了数据库到DataSet桥接器的作用,使应用程序的数据操作统一到DataSet上,而与具体的数据库类型无关。甚至可以针对特殊的数据源编制自己的DataAdpter,从而使我们的应用程序与这些特殊的数据源相兼容。
五、实现要点
适配器模式重在转换接口,它能够使原本不能在一起工作的两个类一起工作,所以经常用在类库复用,代码迁移等方面,有一种亡羊补牢的味道
类适配器和对象适配器可以根据具体实际情况来选用,但一般情况建议使用对象适配器模式
六、效果
通过类的继承或者对象的组合转换已有的接口为目标接口
七、适用性
需要使用一个已经存在的类,但接口与设计要求不符。
希望创建一个可以复用的类,该类可以与其他不相关的类或者是将来不可预见的类协同工作。
八、总结
Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况” ,在遗留代码复用、类库迁移等方面非常有用。
GoF 23 定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。
Adapter模式可以实现的非常灵活,不必拘泥于Gof23中定义的两种结构。例如,完全可以将Adapter模式中的“现存对象”作为新的接口方法参数,来达到适配的目的。
Adapter模式本身要求我们尽可能地使用“面向接口的编程”风格,这样才能在后期很方便地适配。
作者:jiankunking 出处:http://blog.csdn.net/jiankunking
源码下载:http://download.csdn.net/detail/xunzaosiyecao/9543274
小注:
本文部分资料整理自网络,在此表示感谢。
1、 C#设计模式(7)——适配器模式(Adapter Pattern)
2、本杰.NET 张波的PPT资料