work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

设计模式-适配器模式

Posted on 2018-10-07 19:11  work hard work smart  阅读(140)  评论(0编辑  收藏  举报

一、定义

定义:将一个类的接口转换成客户期望的另一个接口

使原本接口不兼容的类可以一起工作

类型:结构型

例如笔记本电源适配器

 

二、适用场景

1、已经存在的类,它的方法和需要不匹配(方法结果相同或相似)

2、不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不相同情况下的解决方案。

 

三、优点

能提高类的透明性和复用,现有的类复用但不需要改变

目标类和适配器类解耦,提高程序的扩展性

符合开闭原则

 

四、缺点

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

增加系统代码可读的难度

 

五、扩展

对象适配器

类适配器。

如果两个选择的话,优先选择对象适配器。

 

六、相关模式

1、适配器模式和外观模式

适配器模式: 复用原来的接口;使两个已有的接口协同工作。

外观模式: 定义新的接口; 在现有的系统中提供一个更为方便的访问入口。适配整个相关的子系统,外观针对的力度更大。

 

七、Coding 类适配器

1. 创建Adaptee类

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

  

2. 创建Target接口

/**
 * 目标
 */
public interface Target {
    void request();
}

  

3. 创建ConcreteTarget 类

public class ConcreteTarget implements  Target {
    @Override
    public void request() {
        System.out.println("ConcreteTarget目标方法");
    }
}

  

4. 创建Adapter 类,do something可以对方法进行扩展

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

  

5. 测试

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

        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}

  

6. UML图

 

八、Coding 对象适配器

与类适配器的区别为:适配器类与被继承类不是继承关系,而是组合关系

1. Adaptee类,ConcreteTarget类,Target接口,Test类与商品类适配器是相同的。

不同的是Adapter类

public class Adapter implements Target{

    private  Adaptee adaptee = new Adaptee();

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

  

2. UML图

 

九、Coding 对象适配器(将220V交流电转为手机5V直流电的适配器)

1.创建AC220 类

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

  

2. 创建接口DC5(目标接口)

public interface DC5 {
    //输出5V直流电
    int outputDC5V();
}

  

3. 创建适配器类

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" + " 输出直流电:" + adapterOutput + "V");
        return adapterOutput;
    }
}

  这里假设使用变压器将220V转为5V

 

4. 测试

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

  

十、在JDK或其他源码中的使用

1、JDK中的XmlAdapter。处理Xml序列化和反序列化使用的。例如将日期指定固定的格式,需要实现

XmlAdapter中的marshal和unmarshal方法。
如下图adapters文件加下都是适配器

 

2. Spring AOP中的AdvisorAdapter接口

public interface AdvisorAdapter {
    boolean supportsAdvice(Advice var1);

    MethodInterceptor getInterceptor(Advisor var1);
}

  比如其中一个类实现了AdvisorAdapter接口

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
    MethodBeforeAdviceAdapter() {
    }

    public boolean supportsAdvice(Advice advice) {
        return advice instanceof MethodBeforeAdvice;
    }

    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice)advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }
}

  

 

 3. Spring MVC中使用的HandlerAdapter接口