首页 > 其他分享 >软件设计模式白话文系列(七)适配器模式

软件设计模式白话文系列(七)适配器模式

时间:2022-11-12 22:00:15浏览次数:41  
标签:11 软件设计 适配器 接口 id 模式 public

1、描述

适配器模式顾名思义就是将某个类的接口转换成客户端期望的另一个接口表示。适配器模式可以消除由于接口不匹配所造成的类兼容性问题。

2、适用性

客户端需要调用现有的业务类,但此业务类的接口又不适用客户端的调用,这时就可以使用适配器模式,提供一个适配器类来达到目的。

3、实现逻辑

适配器模式一般包括下面三种角色类:

  • 目标接口类:定义客户端需要的接口规范。
  • 适配者类:现有的业务类。
  • 适配器类:将现有业务类的接口转换为适合客户端调用的接口

适配器模式有两种实现方式:

一种是继承现有业务类(适配者类)并实现目标接口类,在实现目标接口时调用父类方法,我们称之为类适配器。但这种适配器缺点很明显,继承会使现有的业务类(适配者类)接口对适配器类完全暴露,使得适配器具有现有接⼝类的全部功能,破坏了适配者类的封装性。

通常情况下我们会使用另一种对象适配器,对象适配只需实现目标接口,持有一个适配者类的实例并扩展其方法。这样做的好处是客户端调用适配器类时只能调用自己需要的接口,保证了原有接口的封装性。

4、实战代码

现有用户业务类存在用户 id 查询用户和列表查询返回用户实例对象或其实例集合,但现在新增业务需要通过 id 查询用户信息并返回 JSON 字符串。

4.1 对象适配器

下面代码实现:

/**
 * 用户类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 06:00:46
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Member {
    private Long id;
    private String name;
}

/**
 * 适配者类原有接口 在适配器模式中无实际左右 可以忽略
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:21:36
 */
public interface MemberService {

    Member findMemberById(Long id);

    List<Member> listMember();
}

/**
 * 适配者类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:24:49
 */
public class MemberServiceImpl implements MemberService {
    /**
     * 模拟 DB 初始化点数据
     */
    public static final Map<Long, Member> db = new HashMap<>();

    static {
        db.put(1L, new Member(1L, "张三"));
        db.put(2L, new Member(2L, "李四"));
    }

    @Override
    public Member findMemberById(Long id) {
        return db.get(id);
    }

    @Override
    public List<Member> listMember() {
        return new ArrayList<>(db.values());
    }
}

/**
 * 目标接口类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:21:36
 */
public interface ClientService {

    String findJsonById(Long id);
}

/**
 * 适配器类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:27:46
 */
public class MemberServiceAdapter implements ClientService {
    private MemberService memberService;

    public MemberServiceAdapter(MemberService memberService) {
        this.memberService = memberService;
    }

    @Override
    public String findJsonById(Long id) {
        Member member = memberService.findMemberById(id);
        String jsonStr = JSONUtil.toJsonStr(member);
        return jsonStr;
    }
}

/**
 * 测试类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:29:56
 */
public class Client {
    public static void main(String[] args) {
        MemberServiceAdapter adapter = new MemberServiceAdapter(new MemberServiceImpl());
        System.out.println(adapter.findJsonById(1L));
    }
}

执行结果:

4.2 类适配器

这里这提供适配器类和测试类,其余类同对象适配器一致。

/**
 * 适配器类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:27:46
 */
public class MemberServiceAdapter extends MemberServiceImpl implements ClientService {
    @Override
    public String findJsonById(Long id) {
        Member member = super.findMemberById(id);
        String jsonStr = JSONUtil.toJsonStr(member);
        return jsonStr;
    }
}

/**
 * 测试类
 *
 * @author Eajur.Wen
 * @version 1.0
 * @date 2022-11-11 21:29:56
 */
public class Client {
    public static void main(String[] args) {
        MemberServiceAdapter adapter = new MemberServiceAdapter();
        System.out.println(adapter.findJsonById(1L));
        System.out.println(adapter.listMember());
    }
}

执行结果:

从结果可以看出,类适配器确实达到了我们需要的效果,实现了通过 id 过去对象 JSON 字符串的功能。但是同时也把我们不打算提供给客户端的获取全部列表暴露了出来。 违反了合成复用原则

5、 适配器模式和代理模式

5.1 相同点

适配器模式和代理模式结构同属结构型模式。两者都是通过增加一层中介层(代理模式增加代理类,适配器模式增加适配器类)来实现对原有类的扩展。

5.2 不相同点

两者应用场景有明显不同,适配器模式主要针对新旧接口不一致时导致的客户端无法正常调用的情况,因为我们旧接口类可能存在某种耦合而导致无法重构,为了使用旧接口的某些功能,而创建出来的转换器使旧接口转换成能被客户端使用的新接口。

而代理模式的主要作用是为了不把具体实现暴露出去,且通过代理类做一些处理。代理类接口和原有接口需要保证完全原一致。

标签:11,软件设计,适配器,接口,id,模式,public
From: https://www.cnblogs.com/eajur/p/16884760.html

相关文章

  • 前端学习-CSS-06-元素显示模式
    学习时间:2022.11.12元素显示模式块级元素特点:独占一行宽度默认等于其父母标签,高度由内容撑开宽高可以设置代表元素:div,p,h系列,ul,li,dl,dt,dd,form,header,n......
  • Java消费者生产者模式,并发控制。
    概论举个例子:有一个固定容量的货架,生产者放商品进来,消费者拿商品出去,为了保证正常放入和正常拿出(数据的正确性,不会出现超过容量的存放,拿到空气)。使用同步块中的wait和n......
  • 设计模式学习(二十四):Spring 中使用到的设计模式
    设计模式学习(二十四):Spring中使用到的设计模式作者:Grey原文地址:博客园:设计模式学习(二十四):Spring中使用到的设计模式CSDN:设计模式学习(二十四):Spring中使用到的设计模式......
  • 模板设计模式
    对于模板方法,最好使用final关键字进行修饰。 那么,final修饰变量,又分为两种情况。 一,修饰基本数据类型其值不能被更改 二,修饰引用数据类型其地址值不能被更改,但......
  • 设计模式学习(二十三):中介模式
    设计模式学习(二十三):中介模式作者:Grey原文地址:博客园:设计模式学习(二十三):中介模式CSDN:设计模式学习(二十三):中介模式中介模式中介模式是一种行为型模式。举个简单的例子......
  • 【设计模式】以国足的例子来解释代理模式,希望自己不要被退钱
    文章目录​​1代理模式​​​​1.1代理模式的解释​​​​1.2代理模式的四个对象​​​​2例子​​​​2.1释义​​​​2.2代码​​​​2.3效果图​​​​3静态代理......
  • 设计模式-原型模式
    原型模式的核心在于拷贝源对象,UML类图如下:其中主要有三个角色:客户(client):客户类提出创建对象的请求抽象原型(Prototype):规定拷贝接口具体原型(ConcreatePrototyoe):被拷贝对象......
  • 设计模式学习(二十一):命令模式
    设计模式学习(二十一):命令模式作者:Grey原文地址:博客园:设计模式学习(二十一):命令模式CSDN:设计模式学习(二十一):命令模式命令模式命令模式是一种行为型模式。通过调用者调用......
  • 设计模式学习(二十):备忘录模式
    设计模式学习(二十):备忘录模式作者:Grey原文地址:博客园:设计模式学习(二十):备忘录模式CSDN:设计模式学习(二十):备忘录模式备忘录模式备忘录模式是一种行为型模式。用于记录对......
  • 设计模式学习(十九):访问者模式
    设计模式学习(十九):访问者模式作者:Grey原文地址:博客园:设计模式学习(十九):访问者模式CSDN:设计模式学习(十九):访问者模式访问者模式访问者模式是一种行为型模式。访问者模式......