设计模式-适配器模式

一、适配器模式(结构型模式)
1.定义

适配器模式(Adapter Pattern)是将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。(适配器模式有两种实现方式类适配器和对象适配器)
2.适配器模式角色
**(1).目标(Target)接口:**当前系统业务所期待的接口,它可以是抽象类或接口。(客户端希望的接口)
**(2).适配者(Adaptee)类:**它是被访问和适配的现存组件库中的组件接口。(真正访问的接口)
**(3).适配器(Adapter)类:**它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。(将真正访问的接口转换成客户端希望的接口)
3.代码实现方式
(1).类适配器

(1-1).创建一个目标接口,也就是客户端所期望的接口,定义需要实现的方法。
(1-2).创建适配者(这个适配者一般是原有业务中已经存在的),里面有原来的业务方法。
(1-3).创建适配器实现或者继承适配者,实现目标接口,重写目标接口中的方法,这里的方法中要调用适配者中的super.xxx()方法,然后你要再加一些逻辑啥的自己加吧。
(2).对象适配器
(2-1).创建一个目标接口,也就是客户端所期望的接口,定义需要实现的方法。
(2-2).创建适配者(这个适配者一般是原有业务中已经存在的),里面有原来的业务方法。到这里和上面没什么区别
(2-3).创建适配器实现目标接口,这里组合依赖原来的适配者作为成员变量,一般通过构造注入吧,重写目标接口的方法,这里目标方法中要调用适配者的方法,然后你要加一些逻辑就自己加吧。(对象适配器和类适配器区别在于对象的是组合依赖,类的是通过继承,前者用的多吧,解耦好点)
4.代码实现
(1).类适配器

package com.tw.designPattern.adapter.classAdapter;

/**
 * 目标接口(客户端希望访问的接口)
 */
public interface Target {

    void request();
}

package com.tw.designPattern.adapter.classAdapter;

/**
 * 适配者(真正访问的接口/类)
 */
public class Adaptee {

    public void specificRequest(){
        System.out.println("适配者中的代码被调用!");
    }
}

package com.tw.designPattern.adapter.classAdapter;

/**
 * 类适配器
 */
public class ClassAdapter extends Adaptee implements Target{

    @Override
    public void request() {
        super.specificRequest();
    }
}

package com.tw.designPattern.adapter.classAdapter;

public class ClassAdapterTest {

    public static void main(String[] args) {
        Target target = new ClassAdapter();
        target.request();
    }
}

测试结果

适配者中的代码被调用!

(2).对象适配器
(2-1).场景

模拟新能源汽车的发动机。 新能源汽车的发动机有电能发动机(ElectricMotor)和光能发动机(OpticalMotor)等,各种发动机的驱动方法不同,例如,电能发动机的驱动方法 electricDrive() 是用电能驱动,而光能发动机的驱动方法 opticalDrive() 是用光能驱动,它们是适配器模式中被访问的适配者。
客户端希望用统一的发动机驱动方法 drive() 访问这两种发动机,所以必须定义一个统一的目标接口 Motor, 然后再定义电能适配器(ElectricAdapter)和光能适配器(OpticalAdapter)去适配这两种发动机。
(2-2).具体代码

package com.tw.designPattern.adapter.objectAdapter;

/**
 * 
 * 目标(Target):发动机
 * 
 */
public interface Motor {

    void drive();
}

package com.tw.designPattern.adapter.objectAdapter;

/**
 * 适配者(Adaptee)电能发动机
 */
public class ElectricMotor {

    public void electricDrive(){
        System.out.println("电能发动机驱动汽车!");
    }
}

package com.tw.designPattern.adapter.objectAdapter;

/**
 * 适配者(Adaptee)光能发动机
 */
public class OpticalMotor {

    public void opticalDrive(){
        System.out.println("光能发动机驱动汽车!");
    }
}

package com.tw.designPattern.adapter.objectAdapter;

/**
 * 适配器(Adapter)电能适配器
 */
public class ElectricAdapter implements Motor{

    private ElectricMotor electricMotor;

    public ElectricAdapter(){
        electricMotor = new ElectricMotor();
    }

    @Override
    public void drive() {
        electricMotor.electricDrive();
    }
}

package com.tw.designPattern.adapter.objectAdapter;

/**
 * 适配器(Adapter)光能适配器
 */
public class OpticalAdapter implements Motor{

    private OpticalMotor opticalMotor;

    public OpticalAdapter(){
        opticalMotor = new OpticalMotor();
    }

    @Override
    public void drive() {
        opticalMotor.opticalDrive();
    }
}

package com.tw.designPattern.adapter.objectAdapter;

public class MotorAdapterTest {

    public static void main(String[] args) {
        Motor electricAdapter = new ElectricAdapter();
        electricAdapter.drive();
        Motor opticalAdapter = new OpticalAdapter();
        opticalAdapter.drive();
    }
}

测试结果

电能发动机驱动汽车!
光能发动机驱动汽车!

(2-3).双向适配器

package com.tw.designPattern.adapter.objectAdapter.twoWayAdapter;

/**
 * 目标接口(Target)
 */
public interface TwoWayTarget {

    void request();
}

package com.tw.designPattern.adapter.objectAdapter.twoWayAdapter;

/**
 * 目标实现(Target)
 */
public class TargetRealize implements TwoWayTarget{

    @Override
    public void request() {
        System.out.println("目标代码被调用!");
    }
}

package com.tw.designPattern.adapter.objectAdapter.twoWayAdapter;

/**
 * 目标适配者(Adaptee)
 */
public interface TwoWayAdaptee {

    void specificRequest();
}

package com.tw.designPattern.adapter.objectAdapter.twoWayAdapter;

/**
 * 适配者实现(Adaptee)
 */
public class AdapteeRealize implements TwoWayAdaptee{

    @Override
    public void specificRequest() {
        System.out.println("适配者代码被调用!");
    }
}

package com.tw.designPattern.adapter.objectAdapter.twoWayAdapter;

/**
 * 双向适配器(Adapter)
 */
public class TwoWayAdapter implements TwoWayTarget,TwoWayAdaptee{

    private TwoWayTarget target;

    private TwoWayAdaptee adaptee;

    public TwoWayAdapter(TwoWayTarget target){
        this.target = target;
    }

    public TwoWayAdapter(TwoWayAdaptee adaptee){
        this.adaptee = adaptee;
    }

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

    @Override
    public void specificRequest() {
        target.request();
    }
}

package com.tw.designPattern.adapter.objectAdapter.twoWayAdapter;

public class TwoWayAdapterTest {

    public static void main(String[] args) {
        TwoWayAdaptee adaptee = new AdapteeRealize();
        TwoWayAdapter twoWayTarget = new TwoWayAdapter(adaptee);
        System.out.println("目标通过双向适配器访问适配者!");
        twoWayTarget.request();
        TwoWayTarget target = new TargetRealize();
        TwoWayAdapter twoWayAdaptee = new TwoWayAdapter(target);
        System.out.println("适配者通过双向适配器访问目标!");
        twoWayAdaptee.specificRequest();
    }
}

测试结果

目标通过双向适配器访问适配者!
适配者代码被调用!
适配者通过双向适配器访问目标!
目标代码被调用!

双向适配器个人理解啊
这里定义目标接口(TwoWayTarget)和适配者接口(TwoWayAdaptee),一是为了面向接口开发(依赖倒置原则),二了Java是单继承、多实现的。然后了目标实现(TargetRealize)就是单纯的实现目标接口重写方法,方法里写上自己的业务么,适配者实现(AdapteeRealize)同样的在子类中写上自己的业务,然后双向适配器(TwoWayAdapter)实现目标接口(TwoWayTarget)和适配者接口(TwoWayAdaptee),提供两个构造方法分别注入目标和适配者,然后再分别重写目标接口(TwoWayTarget)的方法,在具体实现中调用适配者的方法,同样重写适配者接口(TwoWayAdaptee)的方法,在具体实现中调用目标的方法,这个就是把类适配结构和对象适配器结构融合在一起了。不够解耦,我觉有实际需要的话可以用的,总比都用对象适配器那样在多谢一个适配器类吧。耦合就耦合吧。
5.优缺点
(1).优点

(1-1). 客户端通过适配器可以透明地调用目标接口。
(1-2).复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
(1-3).将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
(1-4).在很多业务场景中符合开闭原则。
注:以上优点啊基本上都是对象适配器的,一般开发过程中基本上不会用继承的方式的,除非是那种特定场景啊。
(2).缺点
(2-1).在写适配器过程中,你要考虑全应用场景,费脑子,然后加了适配器的话,代码复杂度会高那么一点,不利于维护。
6.应用场景
(1).以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
(2).使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。
说一下在我实际开发中了解的适配器模式啊,springboot中的HandleAdapter,这个看名字就知道了,还有就是HttpServlet也是适配器。有兴趣可以去看下源码。
注:内容参考网络上各种资料,还有一些本人的理解和思想,仅为了学习记录和分享一下自己所学之处,如有不足的地方麻烦大牛指出,如有侵权的地方,请联系删除,谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值