如何对多个if-else判断进行优化

15 篇文章 0 订阅
14 篇文章 0 订阅

如何对多个if-else判断进行优化

当我们遇到需要多个条件判断的业务操作时,最简单直接的办法就是用多个if-else判断,虽然能够实现,但当判断条件过多,甚至是多元判断时,我们的代码就会变得非常不好阅读和维护。

  • 举个例子

这里也可以用switch

if(status === '1'){
      return '未审批'
    }else if(status === '2'){
      return '审批中'
    }else if(status === '3'){
      return '审批通过'
    }else if(status === '4'){
      return '审批退回'
    }else if(status === '5'){
      return '审批异常'
    }

当判断越来越多的时候,优化的空间就来了,接下来和大家分享几种不同场景下关于if-else判断的优化技巧。

1、使用Object对象

适用于单层多个判断

这是一种比较常见的方式,用Object对象把判断收集到一起

const statusArr = {
      '1': '未审批',
      '2': '审批中',
      '3': '审批通过',
      '4': '审批退回',
      '5': '审批异常'
    }
    
function getStatus(Num) {
      return statusArr[Num]
}
    
getStatus('1') //未审批

这样是不是变得优雅一些了呢?可能看下来可能优化的效果没有非常显著,但别忘了,开发时也许不同的状态对应的是一个不同的方法,如果直接写在if-else中,代码就会变得又臭又长,举个例子对比一下

代码仅作举例,没有实际意义

if(status === '1'){
	  //一些操作
      status = '2'
      return '未审批'
    }else if(status === '2'){
       //一些操作
      status = '3'
      return '审批中'
    }else if(status === '3'){
     //一些操作
      status = '4'
      return '审批通过'
    }else if(status === '4'){
     //一些操作
      status = '5'
      return '审批退回'
    }else if(status === '5'){
     //一些操作
      status = '0'
      return '审批异常'
    }

怎么样,是不是已经眼花撩乱。同样优雅一下

const statusArr = {
      '1': ()=>{
        //一些操作
        status = '2'
        return '未审批'
      },
      '2': ()=>{
        //一些操作
        status = '3'
        return '审批中'
      },
      '3': ()=>{
        //一些操作
        status = '4'
        return '审批通过'
      },
      '4': ()=>{
        //一些操作
        status = '5'
        return '审批退回'
      },
      '5': ()=>{
        //一些操作
        status = '0'
        return '审批异常'
      },
    }
    
function getStatus(Num) {
      return statusArr[Num]
}
    
getStatus('1')()

这样的话,将逻辑通过数据的形式维护起来,可读性更好。

以上的方式也可以使用Map对象,相比于Object,Map对象的键就不仅仅只能是一个字符串,可以是任意值,包括函数、对象、基本类型,更加灵活。
实际情况不多,不做举例。
对于Map对象不了解的可以通过这篇博文简单了解。链接: Map对象的使用.

2、通过字符串拼接的方式

和上一种方式道理是一样,拼接后适合多元判断,例如不同的角色,通过字符串拼接的方式,在对象,或Map对象中进行查找相应的逻辑。

举个例子:(比如当我们加上一个角色判断时)

if(role === '打工人') {
	if(status === '1'){
	  //一些操作
    }else if(status === '2'){
       //一些操作
    }else if(status === '3'){
     //一些操作
    }else if(status === '4'){
     //一些操作
    }else if(status === '5'){
     //一些操作
    }
} else if(role === '老板娘') {
	if(status === '1'){
	  //一些操作
    }else if(status === '2'){
       //一些操作
    }else if(status === '3'){
     //一些操作
    }else if(status === '4'){
     //一些操作
    }else if(status === '5'){
     //一些操作
    }
}

可以看到,当同一个方法,不同角色不同状态执行的操作不同时,代码将会变得冗长。
优化的方法:同样使用一个对象收集这种不同的状态,但是由于多元的关系,将角色和状态进行字符串的拼接。

let statusArr = {
      '打工人_1': ()=>{ \\一些操作 },
      '打工人_2': ()=>{ \\一些操作 },
      '打工人_3': ()=>{ \\一些操作 },
      '打工人_4': ()=>{ \\一些操作 },
      '打工人_5': ()=>{ \\一些操作 },
      '老板娘_1': ()=>{ \\一些操作 },
      '老板娘_2': ()=>{ \\一些操作 },
      '老板娘_3': ()=>{ \\一些操作 },
      '老板娘_4': ()=>{ \\一些操作 },
      '老板娘_5': ()=>{ \\一些操作 },
      
    }
function getStatus(role,status) {
      return statusArr[`${role}_${status}`]
}

可以看到,改造之后,更加简明易读,

不过个人认为这种拼接的方式始终不够规范,易读很可能只针对自己,对于接手的可能语义化还不够,下面介绍一种更好的方式。

3、使用对象的方式存放在Map对象上

上面这种方式之所以要拼接在一起,是因为对象的键需要是字符串的限制,如果使用Map对象,键就可以是一个对象、数组或者更多类型,方便了很多。

let statusMap = new Map([
	[{role: '打工人', status : '1'}, ()=>{ /*一些操作*/ }],
	[{role: '打工人', status : '2'}, ()=>{ /*一些操作*/ }],
	[{role: '打工人', status : '3'}, ()=>{ /*一些操作*/ }],
	[{role: '打工人', status : '4'}, ()=>{ /*一些操作*/ }],
	[{role: '打工人', status : '5'}, ()=>{ /*一些操作*/ }],
	[{role: '老板娘', status : '1'}, ()=>{ /*一些操作*/ }],
	[{role: '老板娘', status : '2'}, ()=>{ /*一些操作*/ }],
	[{role: '老板娘', status : '3'}, ()=>{ /*一些操作*/ }],
	[{role: '老板娘', status : '4'}, ()=>{ /*一些操作*/ }],
	[{role: '老板娘', status : '5'}, ()=>{ /*一些操作*/ }],
])
let getStatus = function(role,status) {
    statusMap.forEach((value,key)=>{
	if(JSON.stringify(key) == JSON.stringify({role: role,status: status})){
	value()
	}
})
}
getStatus('打工人','1') // 一些操作

解释一下这段代码:
将状态和角色组成对象放入Map对象中作为键名,将不同的方法作为对应的值。
getStatus方法找到对应的操作并执行
这里有一个小坑,由于键名是对象,所以查找Map对象时不能用Map.get()的方法,原因是由于对象的引用类型的问题,所以我用了这种方式转成字符串来比较。实测没有问题。

以上几种都是基于处理逻辑和配置数据分离的优化方法,这种方法适用于一些不是逻辑不是太复杂的处理。

对于一些复杂的处理逻辑,可以考虑使用责任链模式,这里简单介绍一下这种设计模式。

4、责任链模式
以上的几种方式,都是用穷举的方式在配置数据中查找到相对应的处理方法,而责任链模式就是将整个处理的逻辑改写成一条责任传递链,请求在这条链上传递,直到有一个对象处理这个请求。

举个例子:

在一个购物商城,在五一做了一个活动,所以图书类商品根据购买的金额依次做出以下折扣方案

1、购买满199元,打9折

2、购买满399元,打8折

3、购买满599元以上,打7折;

同样,用最简单的if-else判断写一下

	if(price < 199){
      return '原价'
    }else if(199 <= price && price < 399){
      return '9折'
    }else if(399 <= price && price < 599){
      return '8折'
    }else if(599 <= price ){
      return '7折'
    }

这里看起来并没有很复杂,但是如果在实际业务中,并不仅仅只需要返回一个折扣力度,可能还需要对活动商品、活动库存、是否使用优惠券等等进行计算,这样的话我们所有的逻辑就全部都写在这一个方法内的if判断语句内,可以想象,可读性是很差的。

用责任链模式示范一下:

第一个节点,原价的处理
function BookHandler() {
this.calcPrice = function( price ) {
if ( 199 > price ) {
console.log("原价是:"+ price);
} else {
this.successor.calcPrice( price );
}
}
this.setSuccessor = function( _successor ) {
this.successor = _successor;
}
}
第二个节点,9折的处理
function BookCalc9Handler( _successor ) {
this.calcPrice = function( price ) {
if ( 199 <= price && price < 399 ) {
console.log("原价是:"+ price +";打9折后:" + (price * 0.9));
} else {
this.successor.calcPrice( price );
}
}
this.setSuccessor = function( _successor ) {
this.successor = _successor;
}
}
第三个节点,8折的处理
function BookCalc8Handler() {
this.calcPrice = function( price ) {
if ( 399 <= price && price < 599 ) {
console.log("原价是:"+ price +";打8折后:" + (price * 0.8));
} else {
this.successor.calcPrice( price )
}
}
this.setSuccessor = function( _successor ) {
this.successor = _successor;
}
}
最后,7折的处理
function BookCalc7Handler() {
this.calcPrice = function( price ) {
if ( price >= 599 ) {
console.log("原价是:"+ price +";打7折后:" + (price * 0.7));
} else {
this.successor.calcPrice( price )
}
}
this.setSuccessor = function( _successor ) {
this.successor = _successor;
}
}
 

调用时:

var price = 400;
var bookHandler = new BookHandler();
var bookCalc9Handler = new BookCalc9Handler();
var bookCalc8Handler = new BookCalc8Handler();
var bookCalc7Handler = new BookCalc7Handler();
bookHandler.setSuccessor(bookCalc9Handler);
bookCalc9Handler.setSuccessor(bookCalc8Handler);
bookCalc8Handler.setSuccessor(bookCalc7Handler);
     将所有处理方法连成一条责任链,保证总有一个对象能够处理请求
bookHandler.calcPrice(price);

console.log的结果
在这里插入图片描述

如果不使用责任链链模式、根据当前价格要知道每一级打折信息,最后知道具体是那一层上打折才是符合当前价格的折扣。而使用这种模式,只需要知道当前的处理对象是否能够处理,如果不能处理,就传递给下一个对象,直到有一个对象最终处理,逻辑性更强。

小结

事实上,大部分业务需求都能使用最基本的if-else完成,只不过是简单和繁琐的问题,当我们遇到这类问题,不妨改变一下思路,将自己的代码优雅化,使用上数据配置或责任链模式,你会发现不仅仅是思路的扩展,代码的逻辑都清晰了不少,希望对各位有所帮助。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值