• JAVA【设计模式】适配器模式


    一、定义

    在这里插入图片描述
    适配器模式:将一个类的接口适配成用户所期待的那样,一个适配允许通常因为接口不兼容的不能在一起工作的类,使其在一起工作,做法是将自己的接口包裹在一个已存在的类中

    二、示例:

    模拟场景:
    例如:1、80,90后应该了解万能充电器,实现对各种规格的电池充电功能,这就是生活中典型的适配器,
    例如:2、某些大型的些营销系统,⼤部分常⻅的都是裂变、拉客,例如;你邀请⼀个⽤户开户、或者邀请⼀个⽤户下单,那么平台就会给你返利,多邀多得。同时随着拉新的量越来越多开始设置每⽉下单都会给⾸单奖励,等等,各种营销场景。

    那么这个时候做这样⼀个系统就会接收各种各样的MQ消息或者接⼝,如果⼀个个的去开发,就会耗费
    很⼤的成本,同时对于后期的拓展也有⼀定的难度。此时就会希望有⼀个系统可以配置⼀下就把外部的
    MQ接⼊进⾏,这些MQ就像上⾯提到的可能是⼀些注册开户消息、商品下单消息等等。

    例如:3、大型的商城系统,用户服务模块可能会调用其他第三方的接口。接口的返回参数和名字都不一样,对于用户是否是首单有各种不一样的判断规则。这时我们需要整合一个适配器通用所有规则

    传统编码方式

    一旦扩充新的类型消息,需要转换字符,扩充修改代码

    package com.qf.design.structure.adapter.tradition;
    
    import com.alibaba.fastjson.JSON;
    import com.qf.design.structure.adapter.entity.OrderMq;
    import com.qf.design.structure.adapter.entity.create_account;
    
    import java.util.Date;
    
    public class create_accountMqService {
        /**
         * 代码冗长,需要每次都定义一个新的类,来处理字段,一旦字段发生改变,代码随着也改变
         * @param message
         */
        public void onMessage(String message){
            create_account account= JSON.parseObject(message, create_account.class);
            Date accountDate = account.getAccountDate();
            String address = account.getAddress();
            String number = account.getNumber();
    
    
            //处理自己的业务逻辑
            OrderMq mq=new OrderMq();
            mq.setCreateOrderTime(accountDate);
            mq.setUid(number);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    适配器模式

    定义统一处理的类,所有的第三方mq消息,最终会转换此格式:RebateInfo

    package com.qf.design.structure.adapter.design;
    
    import java.util.Date;
    
    public class RebateInfo {
        /**
         * 自己定义的统一接受处理的类
         */
        private String userId;  // 用户ID
        private String bizId;   // 业务ID
        private Date bizTime;   // 业务时间
        private String desc;    // 业务描述
    
        // ... get/set
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    
        public String getBizId() {
            return bizId;
        }
    
        public void setBizId(String bizId) {
            this.bizId = bizId;
        }
    
        public Date getBizTime() {
            return bizTime;
        }
    
        public void setBizTime(Date bizTime) {
            this.bizTime = bizTime;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        public void setBizTime(String bizTime) {
            this.bizTime = new Date(Long.parseLong("1591077840669"));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    定义适配器,适配所有字段,并且转换:MQAdapter

    package com.qf.design.structure.adapter.design;
    
    import com.alibaba.fastjson.JSON;
    
    import java.lang.reflect.InvocationTargetException;
    import java.util.Map;
    import java.util.Set;
    
    public class MQAdapter {
        public static RebateInfo filter(String strJson, Map<String, String> link) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            return filter(JSON.parseObject(strJson, Map.class), link);
        }
    
        public static RebateInfo filter(Map obj, Map<String, String> link) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            RebateInfo rebateInfo = new RebateInfo();
            for (String key : link.keySet()) {
                Object val = obj.get(link.get(key));
                RebateInfo.class.getMethod("set" + key.substring(0, 1).toUpperCase() + key.substring(1), String.class).invoke(rebateInfo, val.toString());
            }
            return rebateInfo;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    测试:ApiTest

        @Test
        public void mqTest() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, ParseException {
    
            SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = s.parse("2020-06-01 23:20:16");
    
    
            create_account create_account = new create_account();
            create_account.setNumber("100001");
            create_account.setAddress("河北省.廊坊市.广阳区.大学里职业技术学院");
            create_account.setAccountDate(parse);
            create_account.setDesc("在校开户");
    
            HashMap<String, String> link01 = new HashMap<String, String>();
            link01.put("userId", "number");
            link01.put("bizId", "number");
            link01.put("bizTime", "accountDate");
            link01.put("desc", "desc");
            RebateInfo rebateInfo01 = MQAdapter.filter(JSON.toJSONString(create_account), link01);
            System.out.println("mq.create_account(适配前)" + create_account.toString());
            System.out.println("mq.create_account(适配后)" + JSON.toJSONString(rebateInfo01));
    
            System.out.println("");
    
            OrderMq orderMq = new OrderMq();
            orderMq.setUid("100001");
            orderMq.setSku("10928092093111123");
            orderMq.setOrderId("100000890193847111");
            orderMq.setCreateOrderTime(parse);
    
            HashMap<String, String> link02 = new HashMap<String, String>();
            link02.put("userId", "uid");
            link02.put("bizId", "orderId");
            link02.put("bizTime", "createOrderTime");
            RebateInfo rebateInfo02 = MQAdapter.filter(JSON.toJSONString(orderMq), link02);
            System.out.println("mq.orderMq(适配前)" + orderMq.toString());
            System.out.println("mq.orderMq(适配后)" + JSON.toJSONString(rebateInfo02));
    
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    是否为首单的判断,定义统一的规则,抽象接口:IOrderService

    package com.qf.design.structure.adapter.design;
    
    public interface IOrderService {
        boolean isFirst(String uId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    本地的首单规则修改:OrderServiceImpl

    package com.qf.design.structure.adapter.design;
    
    import com.qf.design.structure.adapter.service.OrderService;
    
    public class OrderServiceImpl implements IOrderService{
    
        private OrderService orderService=new OrderService();
        @Override
        public boolean isFirst(String uId) {
            return orderService.queryUserOrderCount(uId)<=1;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第三方的首单规则修改:POPOrderServiceImpl

    package com.qf.design.structure.adapter.design;
    
    import com.qf.design.structure.adapter.service.POPOrderService;
    
    public class POPOrderServiceImpl implements IOrderService{
    
        private POPOrderService  popOrderService=new POPOrderService();
        @Override
        public boolean isFirst(String uId) {
            return popOrderService.isFirstOrder(uId);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试:ApiTest

      @Test
        public void orderTest(){
    
            IOrderService popOrderAdapterService = new POPOrderServiceImpl();
            System.out.println("判断首单,接口适配(POP):" + popOrderAdapterService.isFirst("100001"));
    
            IOrderService insideOrderService = new OrderServiceImpl();
            System.out.println("判断首单,接口适配(自营):" + insideOrderService.isFirst("100001"));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    UML关系图(适配器模式)

    定义一个适配器,统一规则
    在这里插入图片描述
    定义统一规则IOrderService,都去实现此规则:OrderServiceImplPOPOrderServiceImpl
    在这里插入图片描述
    总结:
    从上⽂可以看到不使⽤适配器模式这些功能同样可以实现,但是使⽤了适配器模式就可以让代码:⼲净整洁易于维护、减少⼤量重复的判断和使⽤、让代码更加易于维护和拓展。

    尤其是我们对MQ这样的多种消息体中不同属性同类的值,进⾏适配再加上代理类,就可以使⽤简单的配置⽅式接⼊对⽅提供的MQ消息,⽽不需要⼤量重复的开发。⾮常利于拓展。

  • 相关阅读:
    【JavaScript进阶之旅 ES6篇 第十章】操作原型的方法、super、4种遍历方式、Symbol
    【Kubernetes系列】工作负载资源之ReplicaSet
    Element UI +Vue页面生成二维码的方法
    VoLTE端到端业务详解 | SDP协议
    08-注册BeanPostProcesser
    java计算机毕业设计springboot+vue飞机航空在线订票系统 elementui
    springboo幼儿园书刊信息管理系统毕业设计源码141858
    系分 - 操作系统
    leetCode 1539. 第 k 个缺失的正整数
    mybatis 14: 多对一关联查询
  • 原文地址:https://blog.csdn.net/cativen/article/details/125990492