结构型模式——适配器模式(三)

该项目源码地址:https://github.com/ggb2312/JavaNotes/tree/master/design-pattern (设计模式相关代码与笔记)

1. 定义

将一个类的接口转换成客户期望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。

2. 适用场景

  • 已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)
  • 不是软件设计阶段考虑的设计模式,是随着软件维护。由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案

3. 适配器类型以及角色

对象适配器

符合组合复用原则,使用委托机制。

对象适配器

类适配器

通过类继承实现的。

类适配器

由图可知适配器模式包含一下三个角色:

  1. Target(目标抽象类):目标抽象类定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。在类适配器中,由于Java语言不支持多重继承,所以它只能是接口。

  2. Adapter(适配器类):它可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配。它是适配器模式的核心。

  3. Adaptee(被适配类):被适配类即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类包好了客户希望的业务方法。

4. 相关设计模式

适配器模式和外观模式

  • 适配器复用现有的接口,外观模式则是定义新的接口。

5. 模式实例

5.1 类适配器

Adaptee 有一个被适配器类:

public class Adaptee {
    public void adapteeRequest() {
        System.out.println("被适配者的方法");
    }
}

Target 这个是目标方法的接口:

public interface Target {
    void request();
}

ConcreteTarget 这个是目标方法的实现:

/** 具体的实现类 */
public class ConcreteTarget implements Target {
    @Override
    public void request() {
        System.out.println("ConcreteTarget目标方法");
    }
}

Adapter 而这个就是适配类:继承于被适配类,实现目标方法的接口:

public class Adapter extends Adaptee implements Target {
    @Override
    public void request() {
        super.adapteeRequest();
    }
}

Client 我们来进行测试一下:

public class Test {
    public static void main(String[]args){
        Target target = new ConcreteTarget();
        target.request();

        /** 现在,我们就来通过适配器类来进行实现 */
        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}

测试结果:

测试结果

此时的类图:

类适配器类图

5.2 对象适配器

有一个目标接口:

public interface Target {
    void request();
}

有一个具体的目标类:

/** 具体的实现类 */
public class ConcreteTarget implements Target {
    @Override
    public void request() {
        System.out.println("ConcreteTarget目标方法");
    }
}

以及被适配的类:

public class Adaptee {
    public void adapteeRequest() {
        System.out.println("被适配者的方法");
    }
}

适配类和上面的有一些不同,这里被适配类不是继承过来的,而是作为属性组合到里面来,然后通过对象来调用被适配类里面的方法:

public class Adapter implements Target {

    private Adaptee adaptee = new Adaptee();

    @Override
    public void request() {
        adaptee.adapteeRequest();
    }
}

测试:

public class Test {
    public static void main(String[]args){
        Target target = new ConcreteTarget();
        target.request();

        /** 现在,我们就来通过适配器类来进行实现 */
        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}

测试结果:

测试结果

此时类图:

对象适配类图

5.3 适配器demo

简单的抽象一个场景:手机充电需要将220V的交流电转化为手机锂电池需要的5V直流电,我们的demo就是写一个电源适配器,将 AC220v ——> DC5V

首先有一个被适配的类:220V的类

public class AC220 {
    public int outputAC220V() {
        int output = 220;
        System.out.println("输出220V的交流电"+output+"V");
        return output;
    }
}

我们有一个目标方法的接口:转为5V的直流电

public interface DC5 {
    int outputDC5V();
}

这个就是适配类(使用对象适配):

public class PowerAdapter implements DC5 {

    private AC220 ac220 = new AC220();

    @Override
    public int outputDC5V() {
        int adapterInput = ac220.outputAC220V();
        /** 变压器 */
        int adapterOutput = adapterInput / 44;
        System.out.println("通过PowerAdapter电源适配器输入AC"+adapterInput+"V"+"输出DC:"+adapterOutput+"V");
        return adapterOutput;
    }
}

测试:

public class Test {
    public static void main(String[]args){
        DC5 dc5 = new PowerAdapter();
        dc5.outputDC5V();
    }
}

测试结果:

测试结果

6. 优缺点

优点:

  • 能提高类的透明性和复用,现有的类复用但不需要改变
  • 目标类和适配器类解耦,提高程序扩展性
  • 符合开闭原则

缺点:

  • 适配器编写过程需要全面考虑,可能会增加系统的复杂性
  • 增加系统代码可读的难度

7. 扩展-JDK1.7以及框架源码中的适配器模式

javax.xml.bind.annotation.adapters.XmlAdapter

org.springframework.aop.framework.adapter.AdvisorAdapter、MethodBeforeAdviceAdapter

org.springframework.orm.jpa.JpaVendorAdapter

org.springframework.web.servlet.HandlerAdapter、org.springframework.web.servlet.DispatcherServlet、org.springframework.web.servlet.mvc.Controller

猜你喜欢

转载自www.cnblogs.com/gj-blog/p/10929498.html