阿里P8架构师教你kill祖传石山代码重复/大量ifelse( 二 )
若有新用户类型、用户逻辑 , 只要新增一个XXXUserCart类继承AbstractCart , 实现特殊的优惠和运费处理逻辑即可 。
工厂+模板方法模式 , 消除了重复代码 , 还避免修改既有代码 。 这就是设计模式中的开闭原则:对修改关闭 , 对扩展开放 。
3 注解+反射消除重复代码3.1 需求银行提供了一些API接口 , 对参数的序列化不使用JSON , 而需要我们把参数依次拼在一起构成一个大字符串 。
- 按照银行提供的API文档的顺序 , 把所有参数构成定长的数据 , 然后拼接在一起作为整个字符串
- 因为每种参数都有固定长度 , 未达到长度时需填充:字符串类型的参数不满长度部分需要以下划线右填充 , 也就是字符串内容靠左数字类型的参数不满长度部分以0左填充 , 也就是实际数字靠右货币类型的表示需要把金额向下舍入2位到分 , 以分为单位 , 作为数字类型同样进行左填充 。对所有参数做MD5操作作为签名(为了方便理解 , Demo中不涉及加盐处理) 。
文章插图
文章插图
3.2 菜鸟实现直接根据接口定义实现填充、加签名、请求调用:
public class BankService {// 创建用户public static String createUser(String name, String identity, String mobile, int age) throws IOException {StringBuilder stringBuilder = new StringBuilder();// 字符串靠左 , 多余的地方填充_stringBuilder.append(String.format("%-10s", name).replace(' ', '_'));stringBuilder.append(String.format("%-18s", identity).replace(' ', '_'));// 数字靠右 , 多余的地方用0填充stringBuilder.append(String.format("%05d", age));// 字符串靠左stringBuilder.append(String.format("%-11s", mobile).replace(' ', '_'));// MD5签名stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString()));return Request.Post("http://localhost:45678/reflection/bank/createUser").bodyString(stringBuilder.toString(), ContentType.APPLICATION_JSON).execute().returnContent().asString();}// 支付public static String pay(long userId, BigDecimal amount) throws IOException {StringBuilder stringBuilder = new StringBuilder();// 数字靠右stringBuilder.append(String.format("%020d", userId));// 金额向下舍入2位到分 , 以分为单位 , 作为数字靠右 , 多余的地方用0填充stringBuilder.append(String.format("%010d", amount.setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue()));// MD5签名stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString()));return Request.Post("http://localhost:45678/reflection/bank/pay").bodyString(stringBuilder.toString(), ContentType.APPLICATION_JSON).execute().returnContent().asString();}}
这段代码的重复粒度更细:- 三种标准数据类型的处理逻辑有重复
- 处理流程中字符串拼接、加签和发请求的逻辑 , 在所有方法重复
- 实际方法的入参的参数类型和顺序 , 不一定和接口要求一致 , 容易出错
- 代码层面针对每一个参数硬编码 , 无法清晰地进行核对 , 如果参数达到几十个、上百个 , 出错的概率极大 。
要实现接口逻辑和逻辑实现的剥离 , 首先要以POJO类定义所有的接口参数 。
- 创建用户API的参数
@Datapublic class CreateUserAPI {private String name;private String identity;private String mobile;private int age;}
有了接口参数定义 , 就能通过自定义注解为接口和所有参数增加一些元数据 。- 如下定义一个接口API的注解BankAPI , 包含接口URL地址和接口说明
文章插图
- 定义CreateUserAPI类描述创建用户接口的信息 , 通过为接口增加@BankAPI注解 , 来补充接口的URL和描述等元数据;通过为每一个字段增加@BankAPIField注解 , 来补充参数的顺序、类型和长度等元数据:
- 类似的还有PayAPI类 这2个类继承的AbstractAPI类是一个空实现 , 因为该案例中的接口无公共数据 。
- 王兴称美团优选目前重点是建设核心能力;苏宁旗下云网万店融资60亿元;阿里小米拟增资居然之家|8点1氪 | 美团
- 注册|阿里申请注册“爆改吧!小店”商标,打造线下特色实体小店
- 耽误|被阿里耽误的虾米的一生
- 租赁物业|居然之家(000785)牵手阿里与小米
- IT|信服云为IT基础架构演进提供新思路
- 上市公司|数字化新外贸成为企业巨头新选择 近百家上市公司入驻阿里国际站
- 字节|阿里巴巴、字节跳动、花生日记获“互联网行业公益奖”
- 青山湖|阿里人均年薪百万?95后阿里单身狗陪跑摇号近2年 连青山湖都抛弃他?
- 告诉|阿里大佬告诉你如何一分钟利用Python在家告别会员看电影
- 电商|又一家电商平台倒下惨遭阿里抛弃,负债23亿进入破产重组