哎,曾几何时 

想当年,其实我也特别钟情于 if/else连环写法,上来就是一顿SAO操作,比如举个好理解的简单栗子

一般来说我们正常的后台管理系统都有所谓的角色的概念,不同管理员权限不一样,能够行使的操作也不一样,比如:

  • 系统管理员( ROLE_ROOT_ADMIN):有 A操作权限

  • 订单管理员( ROLE_ORDER_ADMIN):有 B操作权限

  • 普通用户( ROLE_NORMAL):有 C操作权限

比如一个用户进来,我们需要根据不同用户的角色来判断其有哪些行为,这时候SAO代码出现了:

public class JudgeRole {public String judge( String roleName ) {String result = "";if (roleName.equals("ROLE_ROOT_ADMIN")) { // 系统管理员有A权限result = "ROLE_ROOT_ADMIN: " + "has AAA permission";} else if ( roleName.equals("ROLE_ORDER_ADMIN") ) { // 订单管理员有B权限result = "ROLE_ORDER_ADMIN: " + "has BBB permission";} else if ( roleName.equals("ROLE_NORMAL") ) { // 普通用户有C权限result = "ROLE_NORMAL: " + "has CCC permission";} else {result = "XXX";}return result;}
}

这样当系统里有几十个角色时,那几十个 if/else嵌套可以说是非常酸爽了…… 这样一来非常不优雅,别人阅读起来很费劲;二来则是以后如果再复杂一点,或者想要再加条件的话不好扩展;而且代码一改,以前的老功能肯定还得重测,岂不疯了……

所以,如果在不看下文的情况下,你一般会如何去对付这些令人头痛的if/else语句呢?

当然有人会说用 switch/case来写是否会优雅一些呢?答案是:毛区别都没有

接下来简单讲几种改进方式,别再 if/else走天下了


 有枚举为啥不用 

什么角色能干什么事,这很明显有一个对应关系,所以学过的枚举为啥不用呢?

首先定义一个公用接口 RoleOperation,表示不同角色所能做的操作:

public interface RoleOperation {String op();  // 表示某个角色可以做哪些op操作
}

接下来我们将不同角色的情况全部交由枚举类来做,定义一个不同角色有不同权限的枚举类 RoleEnum

public enum RoleEnum implements RoleOperation {// 系统管理员(有A操作权限)ROLE_ROOT_ADMIN {@Overridepublic String op() {return "ROLE_ROOT_ADMIN:" + " has AAA permission";}},// 订单管理员(有B操作权限)ROLE_ORDER_ADMIN {@Overridepublic String op() {return "ROLE_ORDER_ADMIN:" + " has BBB permission";}},// 普通用户(有C操作权限)ROLE_NORMAL {@Overridepublic String op() {return "ROLE_NORMAL:" + " has CCC permission";}};
}

接下来调用就变得异常简单了,一行代码就行了, if/else也灰飞烟灭了:

public class JudgeRole {public String judge( String roleName ) {// 一行代码搞定!之前的if/else没了!return RoleEnum.valueOf(roleName).op();}
}

而且这样一来,以后假如我想扩充条件,只需要去枚举类中加代码即可,而不是去改以前的代码,这岂不很稳!

除了用枚举来消除 if/else,工厂模式也可以实现


 有工厂模式为啥不用 

不同分支做不同的事情,很明显就提供了使用工厂模式的契机,我们只需要将不同情况单独定义好,然后去工厂类里面聚合即可。

首先,针对不同的角色,单独定义其业务类:

// 系统管理员(有A操作权限)
public class RootAdminRole implements RoleOperation {private String roleName;public RootAdminRole( String roleName ) {this.roleName = roleName;}@Overridepublic String op() {return roleName + " has AAA permission";}
}
// 订单管理员(有B操作权限)
public class OrderAdminRole implements RoleOperation {private String roleName;public OrderAdminRole( String roleName ) {this.roleName = roleName;}@Overridepublic String op() {return roleName + " has BBB permission";}
}
// 普通用户(有C操作权限)
public class NormalRole implements RoleOperation {private String roleName;public NormalRole( String roleName ) {this.roleName = roleName;}@Overridepublic String op() {return roleName + " has CCC permission";}
}

接下来再写一个工厂类 RoleFactory对上面不同角色进行聚合:

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 OrderAdminRole("ROLE_ORDER_ADMIN") );roleOperationMap.put( "ROLE_NORMAL", new NormalRole("ROLE_NORMAL") );}public static RoleOperation getOp( String roleName ) {return roleOperationMap.get( roleName );}
}

接下来借助上面这个工厂,业务代码调用也只需一行代码, if/else同样被消除了:

public class JudgeRole {public String judge( String roleName ) {// 一行代码搞定!之前的 if/else也没了!return RoleFactory.getOp(roleName).op();}
}

这样的话以后想扩展条件也很容易,只需要增加新代码,而不需要动以前的业务代码,非常符合“开闭原则”

来,我们接着来,除了工厂模式,策略模式也不妨试一试


 有策略模式为啥不用 

策略模式和工厂模式写起来其实区别也不大!

在上面工厂模式代码的基础上,按照策略模式的指导思想,我们也来创建一个所谓的策略上下文类,这里命名为 RoleContext

public class RoleContext {// 可更换的策略,传入不同的策略对象,业务即相应变化private RoleOperation operation; public RoleContext( RoleOperation operation ) {this.operation = operation;}public String execute() {return operation.op();}
}

很明显上面传入的参数 operation就是表示不同的“策略”。我们在业务代码里传入不同的角色,即可得到不同的操作结果:

public class JudgeRole {public String judge( RoleOperation roleOperation ) {RoleContext roleContext = new RoleContext( roleOperation );return roleContext.execute();}
}
public static void main( String[] args ) {JudgeRole judgeRole = new JudgeRole();String result1 = judgeRole.judge(new RootAdminRole("ROLE_ROOT_ADMIN"));System.out.println( result1 );String result2 = judgeRole.judge(new OrderAdminRole("ROLE_ORDER_ADMIN"));System.out.println( result2 );String result3 = judgeRole.judge(new NormalRole("ROLE_NORMAL"));System.out.println( result3 );
}

 共   勉 

好了,先讲到这里吧,本文仅仅是抛砖引玉,使用了一个极其简单的示例来打了个样,然而其思想可以广泛地应用于实际复杂的业务和场景,思想真的很重要!写代码前还是得多思考一番,考虑是否有更具可扩展性的写法!


后   记

若有错误或者不当之处,可在本公众号内反馈,一起学习交流!

The End来和小伙伴们一起向上生长呀!扫描下方二维码,添加小詹微信,可领取千元大礼包并申请加入 Python 学习交流群,群内仅供学术交流,日常互动,如果是想发推文、广告、砍价小程序的敬请绕道!一定记得备注「交流学习」,我会尽快通过好友申请哦!????长按识别,添加微信(添加人数较多,请耐心等待)????长按识别,关注小詹(扫码回复 1024 领取程序员大礼包)

答应我,别再if/else走天下了可以吗相关推荐

  1. if中加return_答应我,别再 if/else 走天下了可以吗?

    转自:CodeSheep  哎,曾几何时  想当年,其实我也特别钟情于 if/else连环写法,上来就是一顿SAO操作,比如举个好理解的简单栗子: 一般来说我们正常的后台管理系统都有所谓的角色的概念, ...

  2. c替代if else_答应我,别再if/else走天下了可以吗

    作者:hansonwong99 来自:CodeSheep 哎,曾几何时 想当年,其实我也特别钟情于 if/else连环写法,上来就是一顿SAO操作,比如举个好理解的简单栗子: 一般来说我们正常的后台管 ...

  3. cad移动时捕捉不到基点_CAD很难学吗?其实不然,掌握这10个知识你就能走天下!...

    别再说CAD难了,今天给大家分享15个AutoCAD绘图知识,掌握这些你就能走天下~ 1.CAD是由很多命令组成,总体分为两种.一种是输入命令再执行,另一种是选择再执行命令. 2.在执行命令的时候一般 ...

  4. 刷脸支付未来出门只要一张脸就能走天下

    人脸识别支付是随着人脸科技技术的升级发展来的产物,支付宝与微信首先看中了刷脸支付这市场的发展趋势并开始着手在移动支付方式上运用.记得从现金支付到扫码支付,再到刷脸支付,科技的发展在不知不觉中改变着人们 ...

  5. 比淘宝还藏龙卧虎的线下手机卖场,靠什么走天下?

    本文讲的是比淘宝还藏龙卧虎的线下手机卖场,靠什么走天下?,每个城市,都会有一个手机卖场,品牌专卖店.渠道商城.运营商门店.私人摊点.二手交易方.配件零售商--鱼龙混杂地挤在一起. 电商还欠发达的时候, ...

  6. cad命令栏还原默认_CAD十五个必学的命令 掌握后能走天下了

    时常有人问,怎样学CAD. 这个问题实在是太难回答了,认识界面是学,二维设计也是学,三维设计也是学,二次开发也是学... 如果按照普遍所理解的那样,懂绘图就算学会了,那就事情就容易办了. 绘图用得最多 ...

  7. mysql五日均线_中国股市:一根“5日均线”走天下,线上买,线下卖,简直了!...

    炒股,千万不要太"勤劳" 炒股不要太忙,不要太贪心而想抓住每一个机会,在市场方向上不明确,适当休息,劳逸结合可能会取得更好的效果. 可以说,会休息的人,才会炒股,也许,在有些时候, ...

  8. if-else走天下,让CPU分支预测技术浮出水面

    关键字 圈复杂度 CPU分支预测机制 指令 吞吐量 IPS-每秒指令 GIPS-每秒十亿指令 延迟-皮秒 分支预测 if-else走天下 圈复杂度 void sort(int *A) { int i ...

  9. 手机黑科技 中国再一次走在世界的前面

    手机市场变幻莫测,2016年,三星因某些事的影响销量全线下滑:而苹果从硬件到外观都没有给用户带来太多惊喜.中国手机市场形成了"金华OV"四足鼎力的格局.这一年,有很多关键词值得我们 ...

最新文章

  1. Zookeeper 的学习与运用
  2. 把自己的思想记录下来
  3. 寄快递要在面单上写身份证号?市民担心个人信息泄露
  4. Java 读书笔记 (十一) Number Math 类
  5. 第21讲:IP代理池的搭建和使用
  6. php substr 去掉前n位_PHP全栈学习笔记16
  7. 使用Chrome保存网页为mht文件
  8. Docker安装与卸载,配置阿里云镜像加速器
  9. Amoeba 实现Mysql的读写分离
  10. 【数字信号处理】基于matlab GUI数字信号处理系统【含Matlab源码 1088期】
  11. Ubuntu20.04下载安装CMake
  12. 直流调速系统概述工作原理实训教学
  13. C#字符串取第一个和最后一个字符
  14. Java为什么要序列化
  15. Android之自定义一个可播放某一时间段的音乐播放器
  16. 在计算机应用中用于描述算法的是,计算机应用基础习题
  17. 形如e^(ax^2+bx+c)的积分公式的证明
  18. 说说android端实现Airplay多屏互动(一)
  19. 电磁场与仿真软件(32)
  20. Ubuntu 16.04 LTS 64位下安装steam游戏平台

热门文章

  1. PHP源码之数组的内部实现
  2. PHP获取表单值--同时获取下拉框的Value和Text值
  3. PHP对URL进行字符串编码
  4. oracle10g自带的公共同义词,10g ALL_SYNONYMS同义词查询性能下降
  5. mysql中计算问题_MYSQL 数学运算符问题
  6. oclick vue 传参 函数_详解Vue计算属性和侦听属性
  7. postman可以测试websocket吗_小海塔罗娱乐测试2021年可以脱单吗?
  8. python矩阵相加_【python矩阵相加怎么做,这可是证明python功能的大好机会】- 环球网校...
  9. java文件批量重命名6,批量重命名文件DOS脚本
  10. html自动刷新 idea_IDEA设置热部署