关于代码优化,我之前也写了一篇文章,有兴趣的可以看看:
👉我写出这样干净的代码,老板直夸我
今天这篇文章我们又来聊聊代码优化😀。
在平时的开发过程中,你肯定会碰到这样的业务,比如判断车速是否正常。一般编码如下:
float speed = 60f; if (speed > 0f && speed <120f) { Console.log("你的车速正常!!!"); }其实按照面向对象封装的思想,功能应该是模块化的。我们不应该暴露车速判断的具体细节,优化后的编码可以这样写:
if (isNormalSpeed(speed)) { Console.log("你的车速正常!!!"); } private static boolean isNormalSpeed(float speed) { return speed > 0f && speed < 120f; }我们将车速的具体判断隐藏,开发人员只需调用这个方法,无需在自己的代码中编写行为的细节。这样的封装更能复用。
同样,如果判断身份证是否合法,我们一般可能直接这样写:
String idCardNum = "xxxxxxxxxxxx"; if (idCardNum.length() == 18) { Console.log("合法的身份证号!!!"); }当然,我建议这么写:
if (isIdCard(idCardNum)) { Console.log("合法的身份证号!!!"); } private static boolean isIdCard(String idCardNumber) { return idCardNumber.length() == 18; }不要认为这么写多此一举,如果当业务逻辑越来复杂,业务的细节就会会散落在大量的方法中,原本代码的意图会渐渐不明确。会对代码的阅读加大难度。
这里我主要的思想就是:
“编写小而美的函数,将行为细节隐藏,进行模块化调用。
”我们有一个Member实体类,实体类细节如下:
public class Member implements Serializable { private static final long serialVersionUID = 1L; private String id; private String name; ... }我们给name赋值,现在的业务逻辑是,判断这个Member对象是不是我的女朋友,常规编码如下:
Member member = new Member(); member.setName("Zhouzhou"); String userName = "Zhouzhou"; if (StringUtils.isNotBlank(member.getName()) && member.getName().equals(userName)) { Console.log("我的女朋友是:{}",userName); }上面的业务逻辑就是,如果Member中的name为"Zhouzhou",是我的女朋友的判断成立。
上面的代码功能上确实是没什么问题,但是看到这么多.头都晕了。这里违反了编码中的迪米特法则,一个对象应该对其他对象尽可能少的理解。我们优化代码如下:
public class Member implements Serializable { private static final long serialVersionUID = 1L; private String id; private String name; ... public boolean isMyGirlFriend (String userName) { return StringUtils.isNotBlank(this.getName()) && this.getName().equals(userName); } }这里我们增加Member的一个行为isMyGirlFriend(),用于判断实体对象中是不是我的女朋友。调用如下:
if (member.isMyGirlFriend(userName)) { Console.log("我的女朋友是:{}",userName); }实际上面属于充血模型,实体除了Getter/Setter方法,我们还增加了描述实体行为和动作的方法。
关于充血模型,我们再来举个例子。如果我们要专门写一个订单发货的方法,一般情况下我们是这么写的:
/** * 修改订单至发货 * @return */ public void updateOrderDelivery(String orderId,String memberId) { Order order = new Order(); order.setId(orderId); order.setMemberId(memberId); order.setStatus(OrderStatusEnum.DELIVERY.name()); //修改方法 }如果我们采用充血模型:
public class Order { /** * 订单id */ private String id; /** * 下单用户id */ private String memberId; /** * 订单状态 */ private String status; /** * 行为:构建一个发货状态的行为 * @return */ public void buildDeliveryStatus() { this.status = OrderStatusEnum.DELIVERY.name(); } }在实体类中我们增加一个实体的发货行为方法buildDeliveryStatus(),调用如下:
/** * 修改订单至发货 * @return */ public void updateOrderDelivery(String orderId,String memberId) { Order order = new Order(); order.setId(orderId); order.setMemberId(memberId); //这里直接调用订单实体的行为方法 order.buildDeliveryStatus(); //修改方法 }我认为充血模型也是面向对象思想的很好实践,开发人员不需要知道行为具体细节。我们将行为封装,从而实现行为的复用。
这篇文章到这里就结束啦,个人觉得编码细节对于程序员来说还是很重要的。有机会我还会写一篇编码优化的文章。
我写出这样干净的代码,老板直夸我
云南丽江旅游攻略
使用ThreadLocal怕内存泄漏?
Java进阶之路思维导图
程序员必看书籍推荐
3万字的Java后端面试总结(附PDF)
扫码二维码,获取更多精彩。或微信搜Lvshen_9,可后台回复获取资料
1.回复"java" 获取java电子书; 2.回复"python"获取python电子书; 3.回复"算法"获取算法电子书; 4.回复"大数据"获取大数据电子书; 5.回复"spring"获取SpringBoot的学习视频。 6.回复"面试"获取一线大厂面试资料 7.回复"进阶之路"获取Java进阶之路的思维导图 8.回复"手册"获取阿里巴巴Java开发手册(嵩山终极版) 9.回复"总结"获取Java后端面试经验总结PDF版 10.回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF) 11.回复"并发导图"获取Java并发编程思维导图(xmind终极版)另:点击【我的福利】有更多惊喜哦。