结构型模式——适配器(Adapter)
问题背景
当需要将一个接口转换成另一个具有相同参数列表和返回值的接口时,使用适配器。适配器的使用场景一般是移植类库,旧版本类库的接口与新版本的不兼容,因此需要使用适配器来转换接口。假设现有一个排序算法库,通过ISort接口中的Sort方法运行,要将这个库移植到另一个库中,新库的接口和方法为IOrder和Order。
解决方案
在新版类库中创建一个实现类(适配器),此类持有一个对旧版类库接口的引用,此类本身不实现任何功能,只起一个传递调用链的作用:调用此类的接口时,此类继续向下调用旧版类库中的接口,从而实现类库的移植。使用适配器后的程序结构是这样的:
在这个程序中,OrderImpl就是充当适配器的角色,它将Sort接口转换成了Order接口。
上面是适配器的一种实现方式,通过引用来关联适配器和适配对象。另一种方式是让适配器继承适配对象并实现新版接口,同样能达到目的。
效果
- 实现了代码复用。
- 适配器可以对适配对象进行增强。
缺陷
使用适配器会增大扩展旧版类库的工作量。由于适配器与具体的实现绑定,对旧版类库中的实现进行扩展时就需要同时修改或扩展新版类库,增加了工作量。
相关模式
适配器虽然可以增强适配对象,但这并不是初衷。想要增强对象时应该使用更灵活的装饰器和代理,它们支持嵌套,而适配器不支持嵌套。
实现
using System;
namespace Adapter
{
class Client
{
public interface ISort
{
void Sort();
}
public interface IOrder
{
void Order();
}
public class SortImpl : ISort
{
public void Sort()
{
Console.WriteLine("排序中...");
}
}
public class OrderImpl : IOrder
{
private ISort sort;
public OrderImpl()
{
sort = new SortImpl();
}
public void Order()
{
sort.Sort();
}
}
static void Main(string[] args)
{
Console.WriteLine("旧版排序:");
ISort sort = new SortImpl();
sort.Sort();
Console.WriteLine("新版排序:");
IOrder order = new OrderImpl();
order.Order();
}
}
}