适配器模式

DoubleJ

适配器模式简介

使用频率非常高的结构型设计模式,如果系统中存在不兼容的接口便可以通过引入适配器,使得因为接口不兼容的类可以在一起协同使用。

在面向对象的设计中,每个类都承担了一定的职责,不同的类可以相互协作实现更加复杂的工作。结构型模式可以将现有的类或对象组合在一起,形成更加强大的结构

结构型模式分类

类结构型模式

使用类的组合,由多个类组成一个更加复杂的系统,在类结构型模式中一般只存在继承与实现两种关系。

对象结构型模式

使用类与对象的组合,在一个类中定义另一个类的实例对象,然后便可使用该实例对象。

基于合成复用原则,尽量使用关联关系代替继承关系,因此大多数结构型模式都是对象结构型模式。

适配器模式的结构

类适配器模式

image.png

对象适配器模式

image.png

  • Target(目标抽象类/接口):定义所需要的接口。
  • Adapter(适配器类):转换器,属于核心类,对Adaptee和Target进行适配,在类适配器中,通过实现Target接口和继承Adaptee来使二者产生关联;而在对象适配器中,通过继承Target并关联一个Adaptee对象使二者产生联系。
  • Adaptee(适配者类):通常是一个具体的类,包含了调用方需要使用的业务方法。

适配器模式的实现

类适配器模式的实现

class Adaptee
{
    public void AdapteeMethod() { }
}

interface ITarget
{
    void TargetMethod();
}

class Adapter : Adaptee, ITarget
{

    public void TargetMethod()
    {
        base.AdapteeMethod();
    }
}

对象适配器模式的实现

class Adaptee
{
    public void AdapteeMethod() { }
}

interface ITarget
{
    void TargetMethod();
}

class Adapter : ITarget
{
    private Adaptee m_Adaptee;

    public Adapter1(Adaptee adaptee)
    {
        this.m_Adaptee = adaptee;
    }

    public void TargetMethod()
    {
        this.m_Adaptee.AdapteeMethod();
    }
}

电源适配器实例代码

class AC110VAdaptee
{
    public void ACReques()
    {
        Console.WriteLine("电压110v");
    }
}

interface ITarget
{
    void Request();
}

class Client : ITarget
{
    public void Request()
    {
        Console.WriteLine("电压220v");
    }
}

class AC110VAdapter : ITarget
{
    AC110VAdaptee m_Adaptee;

    public AC110VAdapter(AC110VAdaptee adaptee)
    {
        this.m_Adaptee = adaptee;
    }

    public void Request()
    {
        this.m_Adaptee.ACReques();
    }
}

static void Main()
{
    //可采取配置实现
    ITarget t = new Client();
    t.Request();

    ITarget t1 = new AC110VAdapter(new AC110VAdaptee());
    t1.Request();

    Console.ReadKey();
}

缺省适配器模式

当一个接口提供的方法很多而子类又不需要实现接口中的全部方法时,可以先设计一个抽象类实现该接口,并未接口的每一个方法提供一个默认的空实现,之后的子类可以继承抽象类选择性的覆盖父类的方法来实现需求,适用于不想使用一个接口中的所有方法的情况,代码如下:

interface IExample
{
    void Method1();
    void Method2();
    void Method3();
    void Method4();
    void Method5();
    void Method6();
}

abstract class Example : IExample
{
    public virtual void Method1() { }
    public virtual void Method2() { }
    public virtual void Method3() { }
    public virtual void Method4() { }
    public virtual void Method5() { }
    public virtual void Method6() { }
}

class Example1 : Example
{
    public override void Method1()
    {
        //重写父类的方法
    }
}

双向适配器

适配器中同时包含目标类和适配者类的引用,适配者类能够通过适配器调用目标类的方法,目标类也能通过适配器调用适配者类的方法,则属于双向适配器,代码如下:

interface ICat
{
    void CatSpeak();
    void CatAction();
}

class CatTarget : ICat
{
    public void CatSpeak()
    {
        Console.WriteLine("我是一只猫");
    }

    public void CatAction()
    {
        Console.WriteLine("我喜欢吃鱼");
    }
}

interface IFishAdaptee
{
    void FishSpeak();
    void FishAction();
}

class Fishaptee : IFishAdaptee
{
    public void FishSpeak()
    {
        Console.WriteLine("我是一条鱼");
    }

    public void FishAction()
    {
        Console.WriteLine("我喜欢喝水");
    }
}

class AnimalAdapter : ICat, IFishAdaptee
{
    private ICat m_CatTarget;
    private IFishAdaptee m_FishAdaptee;

    public AnimalAdapter(ICat cat, IFishAdaptee adaptee)
    {
        this.m_CatTarget = cat;
        this.m_FishAdaptee = adaptee;
    }

    public void CatAction()
    {
        this.m_FishAdaptee.FishAction();
    }

    public void CatSpeak()
    {
        this.m_CatTarget.CatSpeak();
    }

    public void FishAction()
    {
        this.m_CatTarget.CatAction();
    }

    public void FishSpeak()
    {
        this.m_FishAdaptee.FishSpeak();
    }
}

static void Main()
{
    //猫适配成了鱼, 鱼适配成了猫
    var adapter = new AnimalAdapter(new CatTarget(), new Fishaptee());
    adapter.CatSpeak();
    adapter.CatAction();
    Console.WriteLine();
    adapter.FishSpeak();
    adapter.FishAction();
    Console.ReadKey();
}

运行结果
image.png

适配器模式的优缺点

优点

  • 将目标类和适配者类解耦,无需修改原有结构
  • 增加了类的复用性,同一个适配者类可以在多个不同系统中复用
  • 良好的灵活性于扩展性

缺点(类适配器)

  • 在不支持多重继承的语言中,一次最多只能适配一个适配者类
  • 目标抽象类只能为接口,不能为类,有一定的局限性

适配器模式应用场景

  • 统一多个类的接口设计
  • 创建一个可以重复使用的类,用来和一些彼此之间没有太大关联的类一起工作
  • 现有的接口不符合系统需求,系统需要使用一些现有的类来实现需求,可能没有现有类的源代码
阅读 271
7 声望
2 粉丝
0 条评论
你知道吗?

7 声望
2 粉丝
文章目录
宣传栏