在我们的项目代码中总能看到一些if else这种代码,如果if else 大量出现在我们代码中就会显得特别累赘,代码可读性也很差,那我们该如何去消灭这些丑陋的代码呢,然我们的代码变得优雅且可读性强。
比如,我们在做权限管理系统的时候,不同的角色有不同的操作操作权限,比如 角色a可以干嘛干嘛,角色b可以干嘛干嘛。按照我们以前写代码的惯用思维上来就是无脑if else如:
public class RolePermission {
public String getPermissonByRole(String role){
String result = "";
if ("ROLE_ROOT".equals(role)){
//超级管理员 AAA权限
result = "ROLE_ROOT: " + "has AAA permission";
}else if ("ROLE_ADMIN".equals(role)){
//系统管理员 BBB权限
result = "ROLE_ADMIN: " + "has BBB permission";
}else if ("ROLE_NORMAL".equals(role)){
//普通用户 CCC权限
result = "ROLE_NORMAL: " + "has CCC permission";
}else {
return "XXX";
}
return result;
}
}
这样当系统里有几十个角色时,那几十个 if/else嵌套可以说是非常酸爽了…… 这样一来非常不优雅,别人阅读起来很费劲;二来则是以后如果再复杂一点,或者想要再加条件的话不好扩展;而且代码一改,以前的老功能肯定还得重测,岂不疯了……所以,如果在不看下文的情况下,你一般会如何去对付这些令人头痛的if/else语句呢?当然有人会说用 switch/case来写是否会优雅一些呢?答案是:毛区别都没有!
枚举+接口
什么角色对应干什么事情,学过枚举为啥不用呢?然后定义一个接口,接口只需要返回一个结果(此处演示返回string字符串),然后在枚举类中去实现这个接口。
public interface RoleOperation {
String op();
}
public enum RoleEnum implements RoleOperation {
ROLE_ROOT{
@Override
public String op() {
return "ROLE_ROOT: " + "has AAA permission";
}
},
ROLE_ADMIN{
@Override
public String op() {
return "ROLE_ADMIN: " + "has BBB permission";
}
},
ROLE_NORMAL{
@Override
public String op() {
return "ROLE_NORMAL: " + "has CCC permission";
}
}
}
测试结果
public static void main(String[] args) {
String roleName = "ROLE_ROOT";
String op = RoleEnum.valueOf(roleName).op();
System.out.println(op);
}
控制台信息
ROLE_ROOT: has AAA permission
看一行代码就行了, if/else也灰飞烟灭了:而且这样一来,以后假如我想扩充条件,只需要去枚举类中加代码即可,而不是去改以前的代码,这岂不很稳!
工厂模式
不同分支做不同的事情,很明显就提供了使用工厂模式的契机,我们只需要将不同情况单独定义好,然后去工厂类里面聚合即可。
首先,针对不同的角色,单独定义其业务类,也就是每一个角色要定义一个类,然后类里去返回该业务属性。
//root 用户
public class RootRole implements RoleOperation {
private String role;
public RootRole(String role){
this.role = role;
}
@Override
public String op() {
return "ROLE_ROOT: " + "has AAA permission";
}
}
// admin 用户
public class AdminRole implements RoleOperation {
private String role;
public AdminRole(String role){
this.role = role;
}
@Override
public String op() {
return "ROLE_ADMIN: " + "has BBB permission";
}
}
//普通 用户
public class NormalRole implements RoleOperation {
private String role;
public NormalRole(String role) {
this.role = role;
}
@Override
public String op() {
return "ROLE_NORMAL: " + "has CCC permission";
}
}
// 工厂类
public class RoleFactory {
static Map<String,RoleOperation> map = new HashMap<>();
//加载类的时候去预先加载
static {
map.put("ROLE_ROOT",new RootRole("ROLE_ROOT"));
map.put("ROLE_ADMIN",new AdminRole("ROLE_ADMIN"));
map.put("ROLE_NORMAL",new NormalRole("ROLE_NORMAL"));
}
public static RoleOperation getRoleOperation(String roleName){
return map.get(roleName);
}
}
public static void main(String[] args) {
String roleName = "ROLE_ROOT";
RoleOperation roleName1 = RoleFactory.getRoleOperation(roleName);
String op = roleName1.op();
}
这样的话以后想扩展条件也很容易,只需要增加新代码,而不需要动以前的业务代码,非常符合“开闭原则”,这个与枚举类比较则是不用去修改旧代码,新建角色要去新建一个类,而枚举类则是在原有的枚举类中新增枚举然后去实现对应接口。
策略模式
策略模式和工厂模式写起来其实区别也不大!在上面工厂模式代码的基础上,按照策略模式的指导思想,我们也来创建一个所谓的策略上下文类,这里命名为 RoleContext,也就是将工厂类改成策略类,前者是预加载将其缓存在工厂类中通过角色拿到对应权限,而后者则是直接通过色去驱动这个策略,拿到对应权限。
public class RoleContext {
private RoleOperation roleOperation;
//很明显上面传入的参数 operation就是表示不同的“策略”。我们在业务代码里传入不同的角色,即可得到不同的操作结果:
public RoleContext(RoleOperation roleOperation){
this.roleOperation = roleOperation;
}
public String execute(){
return roleOperation.op();
}
}
public static void main(String[] args) {
String roleName = "ROLE_ROOT";
RoleContext context = new RoleContext(new RootRole(roleName));
System.out.println(context.execute());
}
好了,先讲到这里吧,本文仅仅是抛砖引玉,使用了一个极其简单的示例来打了个样,然而其思想可以广泛地应用于实际复杂的业务和场景,思想真的很重要!写代码前还是得多思考一番,考虑是否有更具可扩展性的写法!
从此处 URL 转载而来