【设计模式】适配器模式


一、适配器模式

一句话总结:有个目标类和目标接口,目标接口不符合我们的要求,于是定义一个适配者,实现目标接口,在适配者中进行自己的实现,使它能满足自己的需求

  • 定义将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作
  • 类型:结构型
  • 适用场景
    • 已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)
    • 不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案
  • 优点
    • 能提高类的透明性和复用,现有的类复用但不需要改变,解决了现有类和目标类不匹配的问题
    • 目标类和适配器类解耦,提高程序扩展性
    • 符合开闭原则,具体的实现都在适配器中,客户端知道的只有适配器类,扩展也只需要扩展适配器类即可
  • 缺点
    • 适配器编写过程需要全面考虑,可能会增加系统的复杂性
    • 增加系统代码可读的难度
  • 扩展
    • 对象适配器:符合组合复用原则,使用委托机制
    • 类适配器:通过类继承来实现
  • 相关设计模式
    • 适配器模式和外观模式:都是对现有类,现有系统的封装,外观定义了新的接口,而适配器则是复用原有的接口,适配器是两个已有的接口协同工作,而外观则是在现有的系统中提供一个更为方便的访问入口,外观模式是适配整个子系统,所以外观针对的对象力度更大
    • 适配器模式和装饰者模式:装饰者模式重点在于增强,适配器模式重点在于适配

二、类适配器 Coding

  • 目标接口和目标实现
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 extends Adaptee implements Target{
    @Override
    public void request() {
        // ...
        super.adapteeRequest();
        // ...
    }
}
  • 测试类
public class Test {
    public static void main(String[] args) {
        // 直接实现
        Target target = new ConcreteTarget();
        target.request();

        // 适配器实现
        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}
  • UML类图
    类适配器UML
  • 说明:可以看到测试方法中,上面两行是目标的普通实现,下面是目标的适配器实现,目标(Target)的具体实现通过Adapter已经移交给了Adaptee,这个是类适配器模式,这里强调的是继承,通过继承来获取被适配者的一些方法,在实现Target的request方法中,可以增加各种逻辑代码。

三、对象适配器 Coding

  • 其他类均未变,改变的是适配器类(Adapter),把原先的继承(被装饰者Adaptee)改成组合的方式
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();
    }
}
  • UML类图
    对象适配器UML
  • 说明:其实两种方式的代码很相似,只不过一个是组合一个是继承,最后的效果都是一样的,目的都是达到适配。

四、实际场景实战

  • 场景描述:将200V的交流电适配成5V的直流电用于给手机充电
  • Coding
  1. 220V的交流电
public class AC220 {
    public int outputAC220V(){
        int output = 220;
        System.out.println("输出交流电"+output+"V");
        return output;
    }
}
  1. 5V的直流电接口
public interface DC5 {
    int outputDC5V();
}
  1. 适配器
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;
    }
}
  1. 测试类
public class Test {
    public static void main(String[] args) {
        DC5 dc5 = new PowerAdapter();
        dc5.outputDC5V();
    }
}
  1. 打印结果
输出交流电220V
使用PowerAdapter输入AC:220V输出DC:5V

五、源码中的应用

  • javax.xml.bind.annotation.adapters.XmlAdapter
    XmlAdapter
  • org.springframework.aop.framework.adapter.AdvisorAdapter:Spring 源码中 AOP 相关的适配器,可以看到它的一个实现
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);
    }
}
  • org.springframework.web.servlet.HandlerAdapter:SpringMVC流程熟悉的话,对于这个处理器适配器应该很熟悉了。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

✦昨夜星辰✦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值