9. 适配器模式(Adapter Pattern)

定义

  • 一个类的接口(被适配者)转换成客户期望的另一个接口(目标)
  • 使原本接口不兼容的类可以一起工作

类型

  • 结构型

适用场景

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

优点

  • 能提高类的透明性和复用,现有的类复用但不需要改变(解决了现有类和目标类不匹配的问题)
  • 目标类和适配器类解耦,提高程序扩展性
  • 符合开闭原则(具体的实现都在适配器中,客户端知道的只有适配器类,如果需要扩展,只需要扩展适配器类,而原有的类是不需要变化的)

缺点

  • 适配器模式编写过程需要全面考虑,可能会增加系统的复杂性
  • 增加系统代码可读难度
  • 如果过多的使用适配器模式,会让我们的系统变得凌乱,不易整理,比如我们调用一个接口。其实内部已经被是配成了另一个接口实现。

扩展

  • 对象适配器模式
    复合组合复用原则,并且使用委托机制
  • 类适配器模式
    通过类继承来实现的

相关设计模式

  • 适配器模式和外观模式

      两者都是对现有的类或系统的封装,
      外观模式
      	1.定义一个新的接口。
      	2.在现有的系统中提供一个更为方便的访问入口。
      适配器模式
      	1.复用一个原有的接口。
      	2.使两个已有的接口协同工作。
    

代码示例

角色

  1. 被适配者Adaptee
  2. 目标接口Target
  3. 适配者Adapter

类适配器模式

步骤

  1. 创建被适配者
//被适配者
public class Adaptee {
    public void apapteeRequest(){
        System.out.println("被适配者的方法");
    }
}
  1. 创建目标接口
//目标接口
public interface Target {
    void request();
}

创建具体的目标类

//具体目标类
public class ConcreteTarget implements Target {
    @Override
    public void request() {
        System.out.println("ConcreteTarget 目标方法");
    }
}
  1. 创建适配者,继承被适配者,实现目标接口方法
//通过Adapter把Adaptee.apapteeRequest()适配给了Target.request()
public class Adapter extends Adaptee implements Target{
    @Override
    public void request() {
    	//...可添加各种逻辑代码
        super.apapteeRequest();
    }
}

UML

在这里插入图片描述
通过类图我们可以看出,Adapter(适配者)继承了Adaptee(被适配者)同时实现了Target(目标接口)。这样Target其实是有两种实现的,一种是ConcreteTarget(具体目标实现),另一个种是通过Adapter适配成Adaptee.apapteeRequest()实现

Test

测试代码

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

执行结果

ConcreteTarget 目标方法
被适配者的方法

对象适配器模式

对与从类适配器模式到对象适配器模式的演进,我们的被适配者Adaptee和目标Target是都不会发生改变的。我们只需要修改适配者Adapter即可

步骤

  1. 我们只会实现Target接口。通过组合的方式。把具体的requet()委托给Adaptee来实现。
public class Adapter implements Target {
    Adaptee adaptee = new Adaptee();
    @Override
    public void request() {
        //....添加逻辑代码
        adaptee.apapteeRequest();
    }
}

UML

在这里插入图片描述

Test

与类适配器模式相同
执行结果不变

ConcreteTarget 目标方法
被适配者的方法

生活场景

手机充电。民用电是220V的交流电,假设我们手机充电需要5V的直流电。并且手机会带电源适配器,它的作用就是把220V的交流电转化成5V的直流电。我们用对象适配器模拟这个生活场景。(在继承和组合的时候我们优先选择组合)

步骤

  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{
    //将220V的交流电组合进来
    private AC220 ac220 = new AC220();

    @Override
    public int outputDC5V() {
        //适配器输入电压
        int adapterInput = ac220.outputAC220V();
        //变压逻辑
        int outPut = adapterInput/44;
        //电源适配器输出电压
        System.out.println("电源适配器: 输入交流电:" + adapterInput + "V,输出直流电:"+ outPut + "V");
        return adapterInput;
    }
  1. Test
public class Test {
    public static void main(String[] args) {
        DC5 dc5 = new PowerAdapter();
        int inputDc = dc5.outputDC5V();
    }
}

执行结果

输出民用交流电220V
电源适配器: 输入交流电:220V,输出直流电:5V
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值