之前的if/else连环写法 想当年,作为一名初学编程的小菜鸟,特别钟情与if/else连环写法,上来就是一顿骚操作,举个例子: 一般来说我们正常的后台管理系统都有所谓的角色的概念,以角色的界定来规定每个角色所具有的权限,不同角色可以行驶的操作也不同,比如:
系统管理员(ROLE_ROOT_ADMIN):假设有A操作权限
订单管理员(ROLE_ORDER_ADMIN):假设有B操作权限
普通用户(ROLE_NORMAL):假设有C操作权限
比如一个用户登陆进来,我们要判断这个用户是处于什么样的角色,然后根据这个用户的角色来赋予他不同的权限,这时候,我们的if/else就出现了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class JudgeRole { public String judge (String roleName) { String result = "" ; if (roleName.equals("ROLE_ROOT_ADMIN" ){ result = "ROLE_ROOT_ADMIN" + "has A permission" ; } else if (roleName.equals("ROLE_ORDER_ADMIN" ){ result = "ROLE_ORDER_ADMIN" + "has B permission" ; }else if (roleName.equals("ROLE_NORMAL" ){ result = "ROLE_NORMAL" + "has C permission" ; }else { result = "NULL" } return result; } }
这样虽然我们写代码写的很爽,只需要简单的if/else就可以完成上面的任务,但是,上面的例子只有三个角色,如果系统里有几十个角色呢 ?那你写几十个if/else……emmmmm我敬你是条汉子。而且且不说要写很多的if/else,看着很low很不优雅啊有木有!而且别人读你的代码的时候,一看到这么多if/else估计头都大了。再者,最重要的是,以后如果你想要扩展角色的话不好扩展,加了之后,老功能还要重测,费时费力… 当然有人会说用switch/case来写,这俩完全没有区别啊,该费事还是费事… 接下来我们说几种解决方法,赶紧告别if/else吧,太low了哈哈。
一、枚举 什么角色可以干什么事,这明显又一个对应关系,所以我们可以用枚举来解决。 首先定义一个公共接口RoleOperation,表示不同角色所能做的操作:
1 2 3 public interface RoleOperation { String op () ; }
接下来我们将不同角色的情况全部交由枚举类来做,定义一个不同角色有不同权限的枚举类RoleEnum:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public enum RoleEnum implements RoleOperation { ROLE_ROOT_ADMIN{ @Override public String op () { return "ROLE_ROOT_ADMIN" + "has A permission!" ; } }, ROLE_ORDER_ADMIN{ @Override public String op () { return "ROLE_ORDER_ADMIN" + "has B permission!" ; } }, ROLE_NORMAL{ @Override public String op () { return "ROLE_NORMAL" + "has C permission!" ; } }; }
接下来调用就变得异常简单了,只需要一行代码。
1 2 3 4 5 6 public class JudgeRole { public String judge (String roleName) { return RoleEnum.valueOf(roleName).op(); } }
而且这样以来,如果我以后再想扩充条件,只需要从枚举类添加代码即可,而不是去改以前的代码。
二、工厂模式 不同分支可以做不同的事情,很明显提供了使用工厂模式的契机,我们只需要将不同情况单独定义好,然后去工厂类里面聚合即可。 首先,针对不同的角色,单独定义其业务类: 系统管理员:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class RootAdminRole implements RoleOperation { private String roleName; public RootAdminRole (String roleName) { this .roleName = roleName; } @Override public String op () { return roleName + "has A permission" ; } }
订单管理员:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class OrderAdminRole implements RoleOperation { private String roleName; public OrderAdminRole (String roleName) { this .roleName = roleName; } @Override public String op () { return roleName + "has B permission" ; } }
普通用户:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class NormalRole implements RoleOperation { private String roleName; public NormalRole (String roleName) { this .roleName = roleName; } @Override public String op () { return roleName + "has C permission" ; } }
接下来,再写一个工厂类RoleFactory对上面不同角色进行聚合:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class RoleFactory { static Map<String, RoleOperation> roleOperationMap = new HashMap<>(); static { roleOperationMap.put("ROLE_ROOT_ADMIN" ,new RootAdminRole("ROLE_ROOT_ADMIN" )); roleOperationMap.put("ROLE_ORDER_ADMIN" ,new RootAdminRole("ROLE_ORDER_ADMIN" )); roleOperationMap.put("ROLE_NORMAL" ,new RootAdminRole("ROLE_NORMAL" )); } public static RoleOperation getOp (String roleName) { return roleOperationMap.get(roleName); } }
接下来借助上面的工厂,业务代码调用也只需要一行代码。
1 2 3 4 5 public class JudgeRole { public String judge (String roleName) { return RoleFactory.getOp(roleName).op(); } }
这样的话以后想扩展条件也很容易,只需要增加新代码,而不需要动以前的业务代码,非常符合“开闭原则 “。
三、策略模式 策略模式和工厂模式在代码上其实差别不大,在上面工厂模式代码的基础上,按照策略模式的指导思想,我们也来创建一个所谓的策略上下文类 ,这里命名为RoleContext:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class RoleContext { private RoleOperation operation; public RoleContext (RoleOperation operation) { this .operation = operation; } public String execute () { return operation.op(); } }
很明显上面传入的参数operation就是表示不同的“策略 ”,我们在业务代码里传入不同的角色,即可得到不同的操作结果:
1 2 3 4 public String judge (RoleOperation operation) { RoleContext roleContext = new RoleContext(operation); return roleContext.execute(); }
四、结束语 以上就是消除if/else的三种方法了,这里我们只是用了一个极其简单的示例来演示,在实际的业务中,可能会更加复杂,我们需要掌握的,只是一种思想,将好的思想多应用于实际开发中。写代码之前多思考,考虑是否有更多的可扩展的写法!