平时写代码过程中,过多if判断语句的存在导致代码产生多层嵌套,影响代码可读性。
if作用
代码中if主要用于控制代码流程:
- 参数合法性校验
- 业务流程走向
if用于参数合法性校验
当if用于参数合法性校验时,避免多层嵌套,可采用以下方式:
使用break,continue
有些人写代码,习惯通过if(condition){}判真的方式控制流程走向,这种方式会造成代码多层嵌套。
如果我们反过来,采用if(!condition){return; break; continue}判假的方式提前退出嵌套则可减少代码嵌套。进入方法,参数不合法,提前return;进入循环,不满足则break退出循环或continue进行快速进入下一次循环。
使用异常
一般情况下,我们使用if主要是为了参数校验,一次又一次的if判断,导致多层嵌套的出现,但又不能不做,很是尴尬。
这种情况,可考虑使用异常统一捕获,try代码块中不做参数校验,所有NPE异常交由外层catch。
当然,使用try..catch,一旦异常触发,可能会降低程序的性能;如果做参数检验仅仅是为了避免极端情况的崩溃,在大部分情况下不会发生异常,那么可以放心使用。
if用于控制业务流程
使用多态
比如以下代码:根据type调用不同通知接口给用户发送通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private void sendNotify(Integer type, String msg) { if (type == 1) { sendEmail(msg); } else if (type == 2){ sendMsg(msg); } else if (type == 3){ sendWechat(msg); } } private void sendWechat(String msg) { System.out.println("wechat" + msg); } private void sendMsg(String msg) { System.out.println("message" + msg); } private void sendEmail(String msg) { System.out.println("email" + msg); }
|
多态解决:
抽象出一个基类
1 2 3 4 5 6 7 8 9 10 11
| public abstract class SendNotify { public void send(String msg) { System.out.println("start send"); doSend(msg); System.out.println("end send"); } public abstract void doSend(String msg); }
|
子类继承父类,同时自己实现具体的发送通知操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class SendEmial extends SendNotify { @Override public void doSend(String msg) { System.out.println("email" + msg); } } public class SendMsg extends SendNotify { @Override public void doSend(String msg) { System.out.println("message" + msg); } } public class SendWechat extends SendNotify { @Override public void doSend(String msg) { System.out.println("wechat" + msg); } }
|
测试:
1 2 3 4 5 6 7 8 9 10 11
| public void testSendNotify() { Map<Integer, SendNotify> sendNotifyMap = new HashMap() {{ put(1, new SendEmial()); put(2, new SendMsg()); put(3, new SendWechat()); }} ; SendNotify sendNotify = sendNotifyMap.get(2); sendNotify.send("hello"); }
|
使用枚举
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
| public enum NotifyEnum { Emial(1, SendEmial.class), Msg(2, SendMsg.class), Wechat(3, SendWechat.class); private Integer type; private Class clazz; NotifyEnum(int type, Class clazz) { this.type = type; this.clazz = clazz; } public static NotifyEnum find(int type) { for (NotifyEnum notify : values()) { if (notify.type == type) { return notify; } } return null; } public Integer getType() { return type; } public Class getClazz() { return clazz; } }
|
测试:
1 2 3 4 5
| public void testEnumSendNotify() throws IllegalAccessException, InstantiationException { NotifyEnum notifyEnum = NotifyEnum.find(3); SendNotify notify = (SendNotify)notifyEnum.getClazz().newInstance(); notify.send("world"); }
|
使用map
通过K-V的方式存入map,调用时不用if判断,跟枚举类似。
1 2 3 4 5 6 7 8 9
| public void testSendNotify() { Map<Integer, SendNotify> sendNotifyMap = new HashMap() ; sendNotifyMap.put(1, new SendEmial()); sendNotifyMap.put(2, new SendMsg()); sendNotifyMap.put(3, new SendWechat()); SendNotify sendNotify = sendNotifyMap.get(2); sendNotify.send("hello"); }
|
抽取方法
通过抽取方法可将多层多层嵌套分配到各个方法中去,减少主方法的嵌套层数,提高可读性。
参考
编写优美的代码之减少嵌套