概念
把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。适配器模式有类的适配器模式和对象的适配器模式两种形式。前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
优缺点
优点:
1、将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构。
2、增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一适配者类可以在多个不同的系统中复用。
3、灵活性和扩展性都非常好,通过使用配置文件,可以很方便的更换适配器,也可以在不修改原有代码的基础上 增加新的适配器,完全复合开闭原则。
缺点:
1、一次最多只能适配一个适配者类,不能同时适配多个适配者。
2、适配者类不能为最终类,在C#中不能为sealed类
3、目标抽象类只能为接口,不能为类,其使用有一定的局限性。
模式的结构
适配器模式(Adapter)包含以下主要角色。
目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
实现模式
假如用的是苹果手机,但是没有苹果充电线,有华为充电线,那么要使用华为充电线给苹果手机充电,此时就需要一个接口进行转换,适配器模式就是用来完成这种转换的。接下来进行具体实现:
类的适配器模式
namespace 适配器
{
/// 华为充电线 typec 苹果充电线 Lightning
class Client
{
/// <summary>
/// 使用华为充电线给苹果手机充电
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
ILightning apple = new Apple();
apple.Recharge();
Console.ReadLine();
}
}
/// <summary>
/// 苹果充电线接口
/// </summary>
public interface ILightning
{
void Recharge();
}
/// <summary>
/// 华为充电线
/// </summary>
public class TypeC
{
public virtual void HuaweiRecharge()
{
Console.WriteLine("华为手机充电");
}
}
/// <summary>
/// 实现苹果手机充电
/// </summary>
public class Apple : TypeC, ILightning
{
public void Recharge()
{
this.HuaweiRecharge();
}
}
}
以上代码实现图:
对象的适配器模式
namespace 适配器
{
class Client
{
static void Main(string[] args)
{
Lightning apple = new Lightning();
apple.Recharge();
Console.ReadKey();
}
}
public class TypeC
{
public void HuaweiRecharge()
{
Console.WriteLine("华为手机充电");
}
}
public class Lightning : TypeC
{
public TypeC tc = new TypeC();
public void Recharge()
{
tc.HuaweiRecharge();
}
}
}
以上代码实现图:
应用场景
适配器模式(Adapter)通常适用于以下场景。
1、系统需要复用现有类,而该类的接口不符合系统的需求;
2、想要建立一个可重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作;
3、对于对象适配器模式,在设计里需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。
模式的扩展
适配器模式(Adapter)可扩展为双向适配器模式,双向适配器类既可以把适配者接口转换成目标接口,也可以把目标接口转换成适配者接口,其结构图如下。