[23种设计模式][结构型]22.适配器模式

204 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情

1.适配器(Adapter)模式概念:

在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。那么如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?这就是本文要说的Adapter模式。

2.意图:

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作。

3.适配器模式的构成:

  1. 目标抽象角色(Target):定义客户要用的特定领域的接口
  2. 适配器(Adapter):调用另一个接口,作为一个转换器
  3. 适配器(Adaptee):定义一个接口,Adapter需要介入
  4. 客户端(Client):协同对象符合Adapter适配器

4.适配器的分类:

有两种类型的适配器模式:

  • 类适配器(采用继承的方式)
  • 对象适配器(采用对象组合的方式)推荐

5.适配器的适用性:

  • 对象需要利用现存的并且接口不兼容的类。
  • 需要创建可重用的类以协调其他接口可能不兼容的类。

6.适配器模式UML类图:

Image.png

7.适配器模式UML序列图:

Image.png

8.NET中的适配器模式:

Adapter模式在.NET Framework中的一个最大的应用就是COM Interop。COM Interop就好像是COM和.NET之间的一条纽带,一座桥梁。我们知道,COM组件对象与.NET类对象是完全不同的,但为了使COM客户程序像调用COM组件一样调用.NET对象,使.NET程序像使用.NET对象一样使用COM组件,微软在处理方式上采用了Adapter模式,对COM对象进行包装,这个包装类就是RCW(Runtime Callable Wrapper)。RCW实际上是runtime生成的一个.NET类,它包装了COM组件的方式,并内部实现对COM组件的调用。如下图所示

Image.png

9.代码示例:

Image.png


类适配:

被适配接口:

public interface Adaptee {

    void output();
}

具体被适配角色A:

public class ConcreteAdapteeA implements Adaptee {

    @Override
    public void output() {
        System.out.println("from ConcreteAdapteeA");
    }
}

具体被适配角色B:

public class ConcreteAdapteeB implements Adaptee {

    @Override
    public void output() {
        System.out.println("from ConcreteAdapteeB");
    }
}

目标接口:

public interface Target {

    void myOutput();
}

具体适配器角色A:

public class ConcreteAdapterA extends ConcreteAdapteeA implements Target {

    @Override
    public void myOutput() {    // 适配
        this.output();
    }
}

具体适配器角色B:

public class ConcreteAdapterB extends ConcreteAdapteeB implements Target {

    @Override
    public void myOutput() {
        this.output();
    }
}

客户角色:

public class Client {

    public static void main(String[] args) {
        Target targetA = new ConcreteAdapterA();
        targetA.myOutput();

        Target targetB = new ConcreteAdapterB();
        targetB.myOutput();
    }
}

对象适配:

被适配接口:

public interface Adaptee {

    void output();
}

具体被适配角色A:

public class ConcreteAdapteeA implements Adaptee {

    @Override
    public void output() {
        System.out.println("from ConcreteAdapteeA");
    }
}

具体被适配角色B:

public class ConcreteAdapteeB implements Adaptee {

    @Override
    public void output() {
        System.out.println("from ConcreteAdapteeB");
    }
}

目标接口:

public interface Target {

    void myOutput();
}

适配器角色:

public class Adapter implements Target {

    private Adaptee adaptee;    // 必须要维护一个Adaptee类型的成员变量

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void myOutput() {
        this.adaptee.output();
    }
}

客户角色:

public class Client {

    public static void main(String[] args) {
        Target target = new Adapter(new ConcreteAdapteeA());
        target.myOutput();

        target = new Adapter(new ConcreteAdapteeB());
        target.myOutput();
    }
}