详解Java实践之适配器模式

目录
  • 一、前言
  • 二、适配器模式介绍
  • 三、案例场景模拟
    • 3.1、场景模拟工程
    • 3.2、场景简述
      • 3.2.1、注册开户MQ
      • 3.2.2、内部订单MQ
      • 3.2.3、第三方订单MQ
      • 3.2.4、查询用户内部下单数量接口
      • 3.2.5、查询用户第三方下单首单接口
  • 四、代码实现
    • 4.1、工程结构
    • 4.2、Mq接收消息实现
  • 五、适配器模式重构代码
    • 5.1、工程结构
    • 5.2、代码实现(MQ消息适配)
      • 5.2.1、统一的MQ消息体
      • 5.2.2、MQ消息体适配类
      • 5.2.3、测试适配类
    • 5.3、代码实现(接口使用适配)
      • 5.3.1、定义统一适配接口
      • 5.3.2、分别实现两个不同的接口
      • 5.3.3、测试适配类
  • 六、总结

一、前言

工作到3年左右很大一部分程序员都想提升自己的技术栈,开始尝试去阅读一些源码,例如SpringMybaitsDubbo等,但读着读着发现越来越难懂,一会从这过来一会跑到那去。甚至怀疑自己技术太差,慢慢也就不愿意再触碰这部分知识。

而这主要的原因是一个框架随着时间的发展,它的复杂程度是越来越高的,从最开始只有一个非常核心的点到最后开枝散叶。这就像你自己开发的业务代码或者某个组件一样,最开始的那部分核心代码也许只能占到20%,而其他大部分代码都是为了保证核心流程能正常运行的。所以这也是你读源码费劲的一部分原因。

框架中用到了设计模式吗?

框架中不仅用到设计模式还用了很多,而且有些时候根本不是一个模式的单独使用,而是多种设计模式的综合运用。与大部分小伙伴平时开发的CRUD可就不一样了,如果都是if语句从上到下,也就算得不上什么框架了。就像你到Spring的源码中搜关键字Adapter,就会出现很多实现类,例如;UserCredentialsDataSourceAdapter。而这种设计模式就是我们本文要介绍的适配器模式。

适配器在生活里随处可见

如果提到在日常生活中就很多适配器的存在你会想到什么?在没有看后文之前可以先思考下。

二、适配器模式介绍

适配器模式的主要作用就是把原本不兼容的接口,通过适配修改做到统一。使得用户方便使用,就像我们提到的万能充、数据线、MAC笔记本的转换头、出国旅游买个插座等等,他们都是为了适配各种不同的,做的兼容。。

除了我们生活中出现的各种适配的场景,那么在业务开发中呢?

在业务开发中我们会经常的需要做不同接口的兼容,尤其是中台服务,中台需要把各个业务线的各种类型服务做统一包装,再对外提供接口进行使用。而这在我们平常的开发中也是非常常见的。

三、案例场景模拟

随着公司的业务的不断发展,当基础的系统逐步成型以后。业务运营就需要开始做用户的拉新和促活,从而保障DAU的增速以及最终ROI转换。

而这时候就会需要做一些营销系统,大部分常见的都是裂变、拉客,例如;你邀请一个用户开户、或者邀请一个用户下单,那么平台就会给你返利,多邀多得。同时随着拉新的量越来越多开始设置每月下单都会给首单奖励,等等,各种营销场景。

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

而适配器的思想方式也恰恰可以运用到这里,并且我想强调一下,适配器不只是可以适配接口往往还可以适配一些属性信息。

3.1、场景模拟工程

itstack-demo-design-6-00

└── src

    └── main

        └── java

            └── org.itstack.demo.design

                ├── mq

                │   ├── create_account.java

                │   ├── OrderMq.java

                │   └── POPOrderDelivered.java

                └── service

                    ├── OrderServicejava

                    └── POPOrderService.java

这里模拟了三个不同类型的MQ消息,而在消息体中都有一些必要的字段,比如;用户ID、时间、业务ID,但是每个MQ的字段属性并不一样。就像用户ID在不同的MQ里也有不同的字段:uId、userId等。同时还提供了两个不同类型的接口,一个用于查询内部订单订单下单数量,一个用于查询第三方是否首单。后面会把这些不同类型的MQ和接口做适配兼容。

3.2、场景简述

3.2.1、注册开户MQ

public class create_account {

    private String number;      // 开户编号
    private String address;     // 开户地
    private Date accountDate;   // 开户时间
    private String desc;        // 开户描述

    // ... get/set
}

3.2.2、内部订单MQ

public class OrderMq {

    private String uid;           // 用户ID
    private String sku;           // 商品
    private String orderId;       // 订单ID
    private Date createOrderTime; // 下单时间     

    // ... get/set
}

3.2.3、第三方订单MQ

public class POPOrderDelivered {

    private String uId;     // 用户ID
    private String orderId; // 订单号
    private Date orderTime; // 下单时间
    private Date sku;       // 商品
    private Date skuName;   // 商品名称
    private BigDecimal decimal; // 金额

    // ... get/set
}

3.2.4、查询用户内部下单数量接口

public class OrderService {

    private Logger logger = LoggerFactory.getLogger(POPOrderService.class);

    public long queryUserOrderCount(String userId){
        logger.info("自营商家,查询用户的订单是否为首单:{}", userId);
        return 10L;
    }

}

3.2.5、查询用户第三方下单首单接口

public class POPOrderService {

    private Logger logger = LoggerFactory.getLogger(POPOrderService.class);

    public boolean isFirstOrder(String uId) {
        logger.info("POP商家,查询用户的订单是否为首单:{}", uId);
        return true;
    }

}

以上这几项就是不同的MQ以及不同的接口的一个体现,后面我们将使用这样的MQ消息和接口,给它们做相应的适配。

四、代码实现

其实大部分时候接MQ消息都是创建一个类用于消费,通过转换他的MQ消息属性给自己的方法。

我们接下来也是先体现一下这种方式的实现模拟,但是这样的实现有一个很大的问题就是,当MQ消息越来越多后,甚至几十几百以后,你作为中台要怎么优化呢?

4.1、工程结构

itstack-demo-design-6-01

└── src

    └── main

        └── java

            └── org.itstack.demo.design

                └── create_accountMqService.java

                └── OrderMqService.java

                └── POPOrderDeliveredService.java

目前需要接收三个MQ消息,所有就有了三个对应的类,和我们平时的代码几乎一样。如果你的MQ量不多,这样的写法也没什么问题,但是随着数量的增加,就需要考虑用一些设计模式来解决。

4.2、Mq接收消息实现

public class create_accountMqService {

    public void onMessage(String message) {

        create_account mq = JSON.parseObject(message, create_account.class);

        mq.getNumber();
        mq.getAccountDate();

        // ... 处理自己的业务
    }

}

三组MQ的消息都是一样模拟使用,就不一一展示了。可以获取源码后学习。

五、适配器模式重构代码

接下来使用适配器模式来进行代码优化,也算是一次很小的重构。

适配器模式要解决的主要问题就是多种差异化类型的接口做统一输出,这在我们学习工厂方法模式中也有所提到不同种类的奖品处理,其实那也是适配器的应用。

在本文中我们还会再另外体现出一个多种MQ接收,使用MQ的场景。来把不同类型的消息做统一的处理,便于减少后续对MQ接收。

在这里如果你之前没要开发过接收MQ消息,可能听上去会有些不理解这样的场景。对此,我个人建议先了解下MQ。另外就算不了解也没关系,不会影响对思路的体会。

再者,本文所展示的MQ兼容的核心部分,也就是处理适配不同的类型字段。而如果我们接收MQ后,在配置不同的消费类时,如果不希望一个个开发类,那么可以使用代理类的方式进行处理。

5.1、工程结构

itstack-demo-design-6-02

└── src

    └── main

        └── java

            └── org.itstack.demo.design

                ├── impl

                │   ├── InsideOrderService.java

                │   └── POPOrderAdapterServiceImpl.java

                ├── MQAdapter,java

                ├── OrderAdapterService,java

                └── RebateInfo,java

适配器模型结构

  • 这里包括了两个类型的适配;接口适配、MQ适配。之所以不只是模拟接口适配,因为很多时候大家都很常见了,所以把适配的思想换一下到MQ消息体上,增加大家多设计模式的认知。
  • 先是做MQ适配,接收各种各样的MQ消息。当业务发展的很快,需要对下单用户首单才给奖励,在这样的场景下再增加对接口的适配操作。

5.2、代码实现(MQ消息适配)

5.2.1、统一的MQ消息体

public class RebateInfo {

    private String userId;  // 用户ID
    private String bizId;   // 业务ID
    private Date bizTime;   // 业务时间
    private String desc;    // 业务描述

    // ... get/set
}
  • MQ消息中会有多种多样的类型属性,虽然他们都有同样的值提供给使用方,但是如果都这样接入那么当MQ消息特别多时候就会很麻烦。
  • 所以在这个案例中我们定义了通用的MQ消息体,后续把所有接入进来的消息进行统一的处理。

5.2.2、MQ消息体适配类

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;
    }

}
  • 这个类里的方法非常重要,主要用于把不同类型MQ种的各种属性,映射成我们需要的属性并返回。就像一个属性中有用户ID;uId,映射到我们需要的;userId,做统一处理。
  • 而在这个处理过程中需要把映射管理传递给Map<String, String> link,也就是准确的描述了,当前MQ中某个属性名称,映射为我们的某个属性名称。
  • 最终因为我们接收到的mq消息基本都是json格式,可以转换为MAP结构。最后使用反射调用的方式给我们的类型赋值。

5.2.3、测试适配类

编写单元测试类

@Test
public void test_MQAdapter() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    create_account create_account = new create_account();
    create_account.setNumber("100001");
    create_account.setAddress("河北省.廊坊市.广阳区.大学里职业技术学院");
    create_account.setAccountDate(new Date());
    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(create_account.toString(), 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(new Date()); 

    HashMap<String, String> link02 = new HashMap<String, String>();
    link02.put("userId", "uid");
    link02.put("bizId", "orderId");
    link02.put("bizTime", "createOrderTime");
    RebateInfo rebateInfo02 = MQAdapter.filter(orderMq.toString(), link02);

    System.out.println("mq.orderMq(适配前)" + orderMq.toString());
    System.out.println("mq.orderMq(适配后)" + JSON.toJSONString(rebateInfo02));
}
  • 在这里我们分别模拟传入了两个不同的MQ消息,并设置字段的映射关系。
  • 等真的业务场景开发中,就可以配这种映射配置关系交给配置文件或者数据库后台配置,减少编码。

测试结果

mq.create_account(适配前){"accountDate":1591024816000,"address":"河北省.廊坊市.广阳区.大学里职业技术学院","desc":"在校开户","number":"100001"}

mq.create_account(适配后){"bizId":"100001","bizTime":1591077840669,"desc":"在校开户","userId":"100001"}

mq.orderMq(适配前){"createOrderTime":1591024816000,"orderId":"100000890193847111","sku":"10928092093111123","uid":"100001"}

mq.orderMq(适配后){"bizId":"100000890193847111","bizTime":1591077840669,"userId":"100001"}

Process finished with exit code 0

  • 从上面可以看到,同样的字段值在做了适配前后分别有统一的字段属性,进行处理。这样业务开发中也就非常简单了。
  • 另外有一个非常重要的地方,在实际业务开发中,除了反射的使用外,还可以加入代理类把映射的配置交给它。这样就可以不需要每一个mq都手动创建类了。

5.3、代码实现(接口使用适配)

就像我们前面提到随着业务的发展,营销活动本身要修改,不能只是接了MQ就发奖励。因为此时已经拉新的越来越多了,需要做一些限制。

因为增加了只有首单用户才给奖励,也就是你一年或者新人或者一个月的第一单才给你奖励,而不是你之前每一次下单都给奖励。

那么就需要对此种方式进行限制,而此时MQ中并没有判断首单的属性。只能通过接口进行查询,而拿到的接口如下;

接口 描述
org.itstack.demo.design.service.OrderService.queryUserOrderCount(String userId) 出参long,查询订单数量
org.itstack.demo.design.service.OrderService.POPOrderService.isFirstOrder(String uId) 出参boolean,判断是否首单
  • 两个接口的判断逻辑和使用方式都不同,不同的接口提供方,也有不同的出参。一个是直接判断是否首单,另外一个需要根据订单数量判断。
  • 因此这里需要使用到适配器的模式来实现,当然如果你去编写if语句也是可以实现的,但是我们经常会提到这样的代码很难维护。

5.3.1、定义统一适配接口

public interface OrderAdapterService {

    boolean isFirst(String uId);

}

后面的实现类都需要完成此接口,并把具体的逻辑包装到指定的类中,满足单一职责。

5.3.2、分别实现两个不同的接口

内部商品接口

public class InsideOrderService implements OrderAdapterService {

    private OrderService orderService = new OrderService();

    public boolean isFirst(String uId) {
        return orderService.queryUserOrderCount(uId) <= 1;
    }

}

第三方商品接口

public class POPOrderAdapterServiceImpl implements OrderAdapterService {

    private POPOrderService popOrderService = new POPOrderService();

    public boolean isFirst(String uId) {
        return popOrderService.isFirstOrder(uId);
    }

}

在这两个接口中都实现了各自的判断方式,尤其像是提供订单数量的接口,需要自己判断当前接到mq时订单数量是否<= 1,以此判断是否为首单。

5.3.3、测试适配类

编写单元测试类

@Test
public void test_itfAdapter() {
    OrderAdapterService popOrderAdapterService = new POPOrderAdapterServiceImpl();
    System.out.println("判断首单,接口适配(POP):" + popOrderAdapterService.isFirst("100001"));   

    OrderAdapterService insideOrderService = new InsideOrderService();
    System.out.println("判断首单,接口适配(自营):" + insideOrderService.isFirst("100001"));
}

测试结果

23:25:47.076 [main] INFO  o.i.d.design.service.POPOrderService - POP商家,查询用户的订单是否为首单:100001

判断首单,接口适配(POP):true

23:25:47.079 [main] INFO  o.i.d.design.service.POPOrderService - 自营商家,查询用户的订单是否为首单:100001

判断首单,接口适配(自营):false

Process finished with exit code 0

从测试结果上来看,此时已经的接口已经做了统一的包装,外部使用时候就不需要关心内部的具体逻辑了。而且在调用的时候只需要传入统一的参数即可,这样就满足了适配的作用。

六、总结

  • 从上文可以看到不使用适配器模式这些功能同样可以实现,但是使用了适配器模式就可以让代码:干净整洁易于维护、减少大量重复的判断和使用、让代码更加易于维护和拓展。
  • 尤其是我们对MQ这样的多种消息体中不同属性同类的值,进行适配再加上代理类,就可以使用简单的配置方式接入对方提供的MQ消息,而不需要大量重复的开发。非常利于拓展。
  • 设计模式的学习过程可能会在一些章节中涉及到其他设计模式的体现,只不过不会重点讲解,避免喧宾夺主。但在实际的使用中,往往很多设计模式是综合使用的,并不会单一出现。

以上就是详解Java实践之适配器模式的详细内容,更多关于Java适配器模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • 23种设计模式(5) java适配器模式

    23种设计模式第五篇:java适配器模式 定义: 将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 角色: 目标(Target)角色:这就是所期待得到的接口,也就是这类的接口是符合我们要求的. 源(Adapee)角色:我们要使用的接口,但是这个接口不符合我们的要求,也就是现在需要适配的接口. 适配器(Adaper)角色:适配器类是适配器模式的核心.适配器把源接口转换成目标接口.显然,这一角色不可以是接口,而必须是具体类. 分类: 1

  • Java适配器模式应用之电源适配器功能详解

    本文实例讲述了Java适配器模式应用之电源适配器功能.分享给大家供大家参考,具体如下: 一.模式定义 存在两种适配器模式 1 对象适配器模式,在这种适配器模式中,适配器容纳一个它包裹的类对象的物理实体. 2 类适配器模式,在这种适配器模式中,适配器继承自已实现的类. 二.模式举例 1 模式分析 我们借用笔计本电源适配器来说明这一模式. 已经存在的交流电源 笔记本电脑 电源适配器 2 适配器模式的静态建模 3 代码举例 3.1 抽象电源建立 package com.demo.power; /**

  • 实例解析Java设计模式编程中的适配器模式使用

    平时我们会经常碰到这样的情况,有了两个现成的类,它们之间没有什么联系,但是我们现在既想用其中一个类的方法,同时也想用另外一个类的方法.有一个解决方法是,修改它们各自的接口,但是这是我们最不愿意看到的.这个时候Adapter模式就会派上用场了. Adapter模式也叫适配器模式,是由GoF提出的23种设计模式的一种.Adapter模式是构造型模式之一,通过Adapter模式,可以改变已有类(或外部类)的接口形式. 适配器 模式 有三种方式,一种是对象适配器,一种是类适配器, 一种是接口适配器 以下

  • Java适配器模式定义与用法示例

    本文实例讲述了Java适配器模式定义与用法.分享给大家供大家参考,具体如下: 将一个类的接口转换成客户想要的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 适配器一共包括3种角色 1.目标:目标是一个接口,该接口是客户想使用的接口 2.被适配者:被适配者是一个已存在的接口或抽象类,这个接口或抽象类需要适配 3.适配器:适配器是一个类,该类实现了目标接口并包含有被适配者的引用,即适配者的指着是对被适配者接口与目标进行适配 package org.zhy.adapte

  • java设计模式之适配器模式(Adapter)

    概述 将一个类的接口转换成用户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 两种实现方式 1.类的适配器模式: 2.对象的适配器模式: 类的适配器模式的UML图,如下: 类的适配器模式把适配的类的API转换成为目标类的API. 上图设计的角色有: 目标角色(Target):这就是所期待得到的接口. 源角色(Adapee):现在需要适配的接口. 适配器角色(Adapter):是本模式的核心,适配器把源接口转换成目标接口. 代码示例: inter

  • Java经典设计模式之适配器模式原理与用法详解

    本文实例讲述了Java经典设计模式之适配器模式.分享给大家供大家参考,具体如下: 适配器模式是把一个类的接口适配成用户所期待的,使得原本由于接口不兼容而不能一起工作的一些类可以在一起工作从而实现用户所期望的功能. 适配器模式的优势: 1. 通过适配器,客户端可以调用统一接口,操作简单直接,并且代码逻辑紧凑,使用起来方便. 2. 代码复用,适配器模式就是解决因为环境要求不相同 的问题,通过适配实现代码复用. 3. 将目标类和适配器类解耦,通过新建一个适配器类来重用现在的类,不用再去重复修改原有代码

  • 详解Java适配器模式

    假期刚结束不久,也没什么好写的,今天就水下文章,讲讲设计模式对开发时的影响,做开发到现在,感觉设计模式对开发的影响还是挺大的. 这次就简单谈谈适配器模式.可能适配器模式感觉比较鸡肋,但是用到的地方还挺多的,特别是合作开发的时候. 1.适配器模式 适配器模式,作为连接两个接口的桥梁.这个概念感觉有点那啥,很少用接口的朋友可能就没有什么感觉,经常面向接口编程的朋友比较能产生共鸣,简单来说,就是写一个适配器(转换器)来对接对象. 2.适配器模式使用 java适配器模式有两种,类适配器和对象适配器 (1

  • Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比

    Java 适配器模式 最近学习java 基础知识,学习适配器的时候疑惑很多,上网查下资料,对于 Adapter的资料很多,但是比较下本篇不错,这里记录下,大家需要的可以看下. 适配器模式就是把一个类的接口转换成客户端所期待的另外一种接口,从而使原接口不匹配而无法在一起工作的的两个类能在一起工作.从功能上说,这些接口不兼容的类一般具有相同或相似的功能.通常我们通过修改该类的接口来解决这种接口不兼容的情形,但是如果我们不愿意为了一个应用而修改各原接口,或者我们压根儿就没有对象的源代码的时候,适配器模

  • Java设计模式之Adapter适配器模式

    一.场景描述 "仪器数据采集器"包含采集数据以及发送数据给服务器两行为,则可定义"仪器数据采集器"接口,定义两方法"采集数据capture"和"发送数据sendData". "PDF文件数据采集器"实现时,要实现"仪器数据采集器"接口,实现"采集数据"方法:目前有"PDF文件内容解析工具"类PdfFileExtractor,该类实现PDF文件的数据

  • 详解Java实践之适配器模式

    目录 一.前言 二.适配器模式介绍 三.案例场景模拟 3.1.场景模拟工程 3.2.场景简述 3.2.1.注册开户MQ 3.2.2.内部订单MQ 3.2.3.第三方订单MQ 3.2.4.查询用户内部下单数量接口 3.2.5.查询用户第三方下单首单接口 四.代码实现 4.1.工程结构 4.2.Mq接收消息实现 五.适配器模式重构代码 5.1.工程结构 5.2.代码实现(MQ消息适配) 5.2.1.统一的MQ消息体 5.2.2.MQ消息体适配类 5.2.3.测试适配类 5.3.代码实现(接口使用适配

  • 详解JAVA设计模式之适配器模式

    适配器模式 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁.这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能. 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能.举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器.您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡. 我们通过下面的实例来演示适配器模式的使用.其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4

  • 详解java实践SPI机制及浅析源码

    1.概念 正式步入今天的核心内容之前,溪源先给大家介绍一下关于SPI机制的相关概念,最后会提供实践源代码. SPI即Service Provider Interface,属于JDK内置的一种动态的服务提供发现机制,可以理解为运行时动态加载接口的实现类.更甚至,大家可以将SPI机制与设计模式中的策略模式建立联系. SPI机制: 从上图中理解SPI机制:标准化接口+策略模式+配置文件: SPI机制核心思想:系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于接口编

  • 详解Java实践之抽象工厂模式

    目录 一.前言 二.开发环境 三.抽象工厂模式介绍 四.案例场景模拟 4.1.场景模拟工程 4.2.场景简述 4.2.1.模拟单机服务 RedisUtils 4.2.2.模拟集群 EGM 4.2.3.模拟集群 IIR 4.3.单集群代码使用 4.3.1.定义使用接口 4.3.2.实现调用代码 五.代码实现 5.1.工程结构 5.2.ifelse实现需求 5.3.测试验证 六.抽象工厂模式重构代码 6.1.工程结构 6.2.代码实现 6.2.1.定义适配接口 6.2.2.实现集群使用服务 6.2.

  • 详解Java实践之建造者模式

    目录 一.前言 二.开发环境 三.建造者模式介绍 四.案例场景模拟 4.1.场景模拟工程 4.2.场景简述 4.2.1.物料接口 4.2.2.吊顶(ceiling) 4.2.3.涂料(coat) 4.2.4.地板(floor) 4.2.5.地砖(tile) 五.代码实现 5.1.工程结构 5.2.ifelse实现需求 5.3. 测试验证 六.建造者模式重构代码 6.1.工程结构 6.2.代码实现 6.2.1.定义装修包接口 6.2.2.装修包实现 6.2.3.建造者方法 6.3.测试验证 七.总

  • Java中File类方法详解以及实践

    目录 File类概述 File类常用构造器 File类常用方法 常用方法示例 createTempFile临时文件创建示例 FilenameFilter文件过滤器示例 总结 File类概述 File类是java.io包下代表与平台无关的文件和目录.File可以新建.删除.重命名文件和目录,但是不能访问文件内容本身,如果需要访问内容的话,需要通过输入/输出流进行访问. File类可以使用文件路径字符串创建File实例,路径既可以是绝对路径,也可以是相对路径.一般相对路径的话是由系统属性user.d

  • 详解Java中AbstractMap抽象类

    jdk1.8.0_144 下载地址:http://www.jb51.net/softs/551512.html AbstractMap抽象类实现了一些简单且通用的方法,本身并不难.但在这个抽象类中有两个方法非常值得关注,keySet和values方法源码的实现可以说是教科书式的典范. 抽象类通常作为一种骨架实现,为各自子类实现公共的方法.上一篇我们讲解了Map接口,此篇对AbstractMap抽象类进行剖析研究. Java中Map类型的数据结构有相当多,AbstractMap作为它们的骨架实现实

  • 详解Java 类的加载机制

    一.类的加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接

  • 详解Java 中的 AutoCloseable 接口

    一.前言 最近用到了 JDK 7 中的新特性 try-with-resources 语法,感觉到代码相对简洁了很多,于是花了点时间详细学习了下,下面分享给大家我的学习成果. 二.简单了解并使用 try-with-resources语法比较容易使用,一般随便搜索看下示例代码就能用起来了.JDK 对这个语法的支持是为了更好的管理资源,准确说是资源的释放. 当一个资源类实现了该接口close方法,在使用try-with-resources语法创建的资源抛出异常后,JVM会自动调用close 方法进行资

  • 详解Java对象的内存布局

    前言 今天来讲些抽象的东西 -- 对象头,因为我在学习的过程中发现很多地方都关联到了对象头的知识点,例如JDK中的 synchronized锁优化 和 JVM 中对象年龄升级等等.要深入理解这些知识的原理,了解对象头的概念很有必要,而且可以为后面分享 synchronized 原理和 JVM 知识的时候做准备. 对象内存构成 Java 中通过 new 关键字创建一个类的实例对象,对象存于内存的堆中并给其分配一个内存地址,那么是否想过如下这些问题: 这个实例对象是以怎样的形态存在内存中的? 一个O

随机推荐