用示例代码来帮你了解适配器模式
对于“设计模式”这个词大家肯定都不陌生,很多框架也用到了设计模式,但是大部分的开发者应该是没有深入的了解过,我准备硬肝下这23设计模式作为专题文章的开端,一共23种设计模式,我尽量在<23天肝完。
为什么要学习设计模式:https://blog.csdn.net/kaituozhe_sh/article/details/107922339
在我大学四年,对设计模式也没有什么概念,写代码就想着能实现就可以了,不会有设计模式那样的思想,但是当学习到了框架的时候,对于设计模式才有了一些更深入的了解,使用设计模式的代码在扩展性上会比暴力的代码更容易维护,特别是当一个程序猿离职了后,你去接手它的代码,里面是一大堆if else,这样真的会崩溃,修改都不知道从何下手
硬肝系列目录
创建型模式
结构型模式
行为型模式
到目前为止、23种设计模式的创建型模式已经给大家肝完了,现在我们进入到一个全新的章节,结构型模式!!!
适配器模式
什么是适配器?
对于手机和电源来说,充电器就是一个适配器,充电器将220V的额定电压转换为我手机所需要充电的电压,要不然用220V来对手机进行充电,我相信目前为止的手机都接受不了这么大的电压,还有一些耳机转接头、屏幕转接头也是一类适配器,那对于我们代码来说什么样的才叫适配器呢?我举个例子A、B两个系统传输数据可能在A系统的用户id字段为userId
,但是B系统的用户id字段为uId
,这样就出现分歧了,B系统得将userId
转换为uId
才可以储存吧,这里就相当于用到我们适配器模式的开发原理了,随着系统越来越大,子系统越来越多,各个子系统的信息传递就成了很大的一个问题,而且子系统有些又是外包出去的项目,这就导致了一个问题,数据库设计的字段设计大部分是不一样的,这就需要从其他系统接收信息的时候需要我们这边自己处理一下才能存库或者进行下一步的操作
到目前为止、对于实际项目我接触过的有利用适配器模式进行开发的系统就有一个,我用一个图来给大家说明
通过我们上面的图可以看出,适配器前置也可以作为一个小系统,也可以处理业务逻辑,但是最主要的是监听消息以及消息转换,转换成我们子系统所需要的消息格式,所以对于多个子系统的互相通信,适配器还是很有需要的
现在我们用一个比较简单的代码来模拟实际项目用到适配器模式的事件
举个栗子,像平常我们使用的TB、JD等购物软件,当用户下单的时候,会给你一定的积分吧、有时候还会送一些小礼品,因为现在几乎所有的互联网公司都是使用的微服务架构,各个子系统各自执行,互不影响,通过网络进行消息的传递,有的时候需要消息队列来进行通信,但是消息队列只负责消息的发送与持久化,不能帮你更改里面的内容啊,所以我们需要在各自的子系统中维护其他子系统传递过来的消息,现在我们模拟三个子系统之间的通信,订单系统、礼品系统和积分系统
订单系统需要传递的消息:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderTransferAdapter {
private String userId;
private String orderId;
private String address;
private BigDecimal monetary;
private Date createDate;
}
这就出现了一个问题,我礼品系统的用户Id不叫userId
,而是uId
,orderId
叫oId
,所以我们需要一个适配器来转换订单系统传过来的字段,变成我们所需要的格式
定义一个适配器抽象类:
@Data
public abstract class AbstractTransferAdapter<T> {
//json为其他子系统传过来的消息
public abstract T transfer(JSONObject json);
}
礼品类来继承抽象类,实现适配器模式:
public class GiftTransferAdapter extends AbstractTransferAdapter<GiftTransferAdapter.TargetObject>{
@Override
public TargetObject transfer(JSONObject json) {
return new TargetObject
.TargetObjectBuilder()
.uid(json.getStr("userId"))
.oid(json.getStr("orderId"))
.userAddress(json.getStr("address"))
.createDate(json.getDate("createDate"))
.build();
}
@Data
@Builder
static class TargetObject{
private String uid;
private String oid;
private String userAddress;
private Date createDate;
}
}
从上面的代码我们可以看出,根据订单系统传过来的json格式字符串,我们通过定义一个静态内部类,内部类的字段就是我们礼品系统所需要的字段名称,transfer()返回的就是礼品系统所需要的对象
积分系统也是一样的道理,直接上代码:
public class IntegralTransferAdapter extends AbstractTransferAdapter<IntegralTransferAdapter.TargetObject>{
@Override
public TargetObject transfer(JSONObject json) {
return new TargetObject
.TargetObjectBuilder()
.consumerId(json.getStr("userId"))
.oid(json.getStr("orderId"))
.consume(json.getBigDecimal("monetary"))
.createDate(json.getDate("createDate"))
.build();
}
@Data
@Builder
static class TargetObject{
private String consumerId;
private String oid;
private BigDecimal consume;
private Date createDate;
}
}
积分系统的用户Id在这称作consumerId
,原理和礼品系统一样
最后我们写一个测试类来测试我们的代码是否正确
public class TestAdapter {
public static void main(String[] args) {
//模拟用户下单
//创建订单
OrderTransferAdapter order = new OrderTransferAdapter();
order.setUserId("ALiangX");
UUID uuid = UUID.randomUUID();
order.setOrderId(uuid.toString());
order.setAddress("中国山东济南");
order.setMonetary(new BigDecimal(2021.314));
order.setCreateDate(new Date());
//将需要传输的字段放到json字符串中
JSONObject jsonObject = new JSONObject();
jsonObject.set("userId",order.getUserId());
jsonObject.set("orderId",order.getOrderId());
jsonObject.set("address",order.getAddress());
jsonObject.set("monetary",order.getMonetary().toString());
jsonObject.set("createDate",order.getCreateDate().toString());
System.out.println("订单系统传输的数据" + jsonObject.toString() + "\n");
//模拟网络传输----------------kafka~~~~过了0.00001s通过消息队列到达子系统
GiftTransferAdapter gift = new GiftTransferAdapter();
//得到一个礼品系统需要的对象giftObject
GiftTransferAdapter.TargetObject giftObject = gift.transfer(jsonObject);
System.out.println("礼品系统通过适配器转换得到的数据: \n uId: " + giftObject.getUid() +
"\n oId: " + giftObject.getOid() +
"\n UserAddress: " + giftObject.getUserAddress() +
"\n CreateDate: " + giftObject.getCreateDate());
IntegralTransferAdapter integral = new IntegralTransferAdapter();
//得到一个积分系统需要的对象integralObject
IntegralTransferAdapter.TargetObject integralObject= integral.transfer(jsonObject);
System.out.println("积分系统通过适配器转换得到的数据: \n consumerId: " + integralObject.getConsumerId() +
"\n oId: " + integralObject.getOid() +
"\n consume: " + integralObject.getConsume() +
"\n CreateDate: " + integralObject.getCreateDate());
}
}
输出结果:
订单系统传输的数据{"address":"中国山东济南","monetary":"2021.314000000000078216544352471828460693359375","orderId":"c418a764-3947-4d12-a799-d24cb3450fad","userId":"ALiangX","createDate":"Fri Mar 19 16:20:40 CST 2021"}
礼品系统通过适配器转换得到的数据:
uId: ALiangX
oId: c418a764-3947-4d12-a799-d24cb3450fad
UserAddress: 中国山东济南
CreateDate: Fri Mar 19 16:20:40 CST 2021
积分系统通过适配器转换得到的数据:
consumerId: ALiangX
oId: c418a764-3947-4d12-a799-d24cb3450fad
consume: 2021.314000000000078216544352471828460693359375
CreateDate: Fri Mar 19 16:20:40 CST 2021
子系统得到数据之后就可以进行自己的业务处理了,这里只是简单的模拟了一下适配器模式的应用,通过适配器模式,我们再也不用为数据库字段设计不同而苦恼,随着系统的不断深入,拥有坚实的基础还是非常重要的!!!
完成:TO: 2021/3/19 16:55