设计模式(6)——适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。我准备用一个小例子来讲述这个适配器模式。

原型

本来是这样的,有个用USB连接的东西,突然有一天说增加了GIGE网口的连接方式,根据“开闭原则”我不想改变之前的USB类,同时,IUSB类的各种方法我们还是需要实现的,那么我们就需要用到适配器模式。

class Program
{
    static void Main(string[] args)
    {
        IUSB usb = new USB();
        usb.Connect();
        Console.Read();
    }
}
class USB : IUSB
{
    public void Connect()
    {
        Console.WriteLine("USB连接成功");
    }
}
interface IUSB
{
    void Connect();
}

类图

在这里插入图片描述

类的适配器模式

当我们要访问的接口IUSB中没有我们想要的方法 ,却在另一个接口IGIGE中发现了合适的方法,我们又不能改变访问接口IUSB,在这种情况下,我们可以定义一个适配器ConnectAdapter类来进行中转,这个适配器ConnectAdapter类要实现我们访问的接口IUSB,这样我们就能继续访问当前接口IUSB中的方法,然后再继承接口IGIGE的实现类GIGE类,这样我们可以在适配器ConnectAdapter类中访问接口IGIGE的方法了,这时我们在适配器ConnectAdapter类中的接口IUSB方法中直接引用GIGE中的Connect方法,这样就完成了一个简单的类适配器。

class Program
{
    static void Main(string[] args)
    {
        IUSB gige = new ConnectAdapter();
        gige.Connect();
        Console.Read();
    }
}
class GIGE : IGIGE
{
    public void GIGEConnect()
    {
        Console.WriteLine("GIGE连接成功");
    }
}
class USB : IUSB
{
    public void Connect()
    {
        Console.WriteLine("USB连接成功");
    }
}
interface IGIGE
{
    void GIGEConnect();
}
interface IUSB
{
    void Connect();
}
class ConnectAdapter : GIGE, IUSB
{
    public void Connect()
    {
        this.GIGEConnect();
    }
}

类图

在这里插入图片描述

类的适配器模式的优点与缺点

类的适配器模式的优点:

  • 可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”
  • 可以重新定义Adaptee(被适配的类)的部分行为,因为在类适配器模式中,Adapter是Adaptee的子类
  • 仅仅引入一个对象,并不需要额外的字段来引用Adaptee实例(这个即是优点也是缺点)。

类的适配器模式的缺点:

  • 用一个具体的Adapter类对Adaptee和Target进行匹配,当如果想要匹配一个类以及所有它的子类时,类的适配器模式就不能胜任了。因为类的适配器模式中没有引入Adaptee的实例,光调用this.SpecificRequest方法并不能去调用它对应子类的SpecificRequest方法。
  • 采用了 “多继承”的实现方式,带来了不良的高耦合。

对象的适配器模式

当我们要访问的接口IUSB中没有我们想要的方法 ,却在另一个接口IGIGE中发现了合适的方法,我们又不能改变访问接口IUSB,在这种情况下,我们可以定义一个适配器ConnectAdapter类来进行中转,这个适配器ConnectAdapter类要实现我们访问的接口IUSB,这样我们就能继续访问当前接口IUSB中的方法,定义一个带参数的构造器来构造注入,增加可测试性,再在IUSB接口的方法实现中使用私有的对象调用其来源于IGIGE接口的方法。

class Program
{
    static void Main(string[] args)
    {
        IUSB gige = new ConnectAdapter(new GIGE());
        gige.Connect();
        Console.Read();
    }
}
class GIGE : IGIGE
{
    public void GIGEConnect()
    {
        Console.WriteLine("GIGE连接成功");
    }
}
class USB : IUSB
{
    public virtual void Connect()
    {
        Console.WriteLine("USB连接成功");
    }
}

interface IGIGE
{
    void GIGEConnect();
}
interface IUSB
{
    void Connect();
}
class ConnectAdapter : USB
{
    private readonly IGIGE _gige;
    public ConnectAdapter(IGIGE gige)
    {
        this._gige = gige;
    }
    public override void Connect()
    {
        _gige.GIGEConnect();
    }
}

类适配器与对象适配器的使用场景一致,仅仅是实现手段稍有区别,二者主要用于如下场景:

  • 想要使用一个已经存在的类,但是它却不符合现有的接口规范,导致无法直接去访问,这时创建一个适配器就能间接去访问这个类中的方法。
  • 我们有一个类,想将其设计为可重用的类(可被多处访问),我们可以创建适配器来将这个类来适配其他没有提供合适接口的类。

类图

在这里插入图片描述

对象的适配器模式的优点与缺点

对象的适配器模式的优点:

  • 可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”
  • 采用 “对象组合”的方式,更符合松耦合。

对象的适配器模式的缺点:

  • 使得重定义Adaptee的行为较困难,这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。

接口的适配器模式

这里为了更好的理解,稍微反一下,因为网口有设置IP的操作,而USB没有,但是IUSB这个接口已经定义了好多方法,你必须实现他,那么就可以首先先用一个类来继承IGIGE,空实现,然后再定义一个类重载IGIGE接口的对自己有用的方法,本例就是Connect方法。

class Program
{
    static void Main(string[] args)
    {
        IGIGE usb = new USB();
        usb.Connect();
        Console.Read();
    }
}
interface IGIGE
{
    void Connect();
    void SetIP();
}
abstract class ConnectAdapter : IGIGE
{
    public virtual void Connect() { }

    public virtual void SetIP() { }
}
class USB : ConnectAdapter
{
    public override void Connect()
    {
        Console.WriteLine("USB连接成功");
    }
}

类图

在这里插入图片描述

接口的适配器模式的优点和缺点

接口的适配器模式的优点:

  • 可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”
  • 采用接口的方式,更符合松耦合。

对象的适配器模式的缺点:

  • 没有用到的接口的其他几个方法,它们的实现用的空实现

本文主要借鉴了《Gof设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值