Catalog
  1. 1. 之前的if/else连环写法
  2. 2. 一、枚举
  3. 3. 二、工厂模式
  4. 4. 三、策略模式
  5. 5. 四、结束语
如何巧妙的告别if-else语句

之前的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"){//系统管理员A权限
result = "ROLE_ROOT_ADMIN" + "has A permission";
} else if(roleName.equals("ROLE_ORDER_ADMIN"){//订单管理员B权限
result = "ROLE_ORDER_ADMIN" + "has B permission";
}else if(roleName.equals("ROLE_NORMAL"){//用户C权限
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 {
//系统管理员,A权限
ROLE_ROOT_ADMIN{
@Override
public String op(){
return "ROLE_ROOT_ADMIN" + "has A permission!";
}
},
//订单管理员,B权限
ROLE_ORDER_ADMIN{
@Override
public String op(){
return "ROLE_ORDER_ADMIN" + "has B permission!";
}
},
//用户,C权限
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的三种方法了,这里我们只是用了一个极其简单的示例来演示,在实际的业务中,可能会更加复杂,我们需要掌握的,只是一种思想,将好的思想多应用于实际开发中。写代码之前多思考,考虑是否有更多的可扩展的写法!

Author: zycode1561
Link: https://zycode1561.github.io/2019/12/10/%E5%A6%82%E4%BD%95%E5%B7%A7%E5%A6%99%E7%9A%84%E5%91%8A%E5%88%ABif-else%E8%AF%AD%E5%8F%A5/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
  • 支付宝

Comment