The Responsibility Chain Model of javascript

Keywords: Javascript Mobile

Responsibility chain model

Responsibility chain mode: similar to a domino card, by requesting the first condition, it will continue to perform the following conditions until the result is returned.


if-else statements can be optimized in projects

Scene demo

Scenario: An e-commerce has a preferential policy for users who have paid a deposit. After formal purchase, users who have paid a deposit of 500 yuan will receive a 100 yuan coupon. Users who have paid a deposit of 200 yuan can receive a 50 yuan coupon. Users who have not paid a deposit can only buy normally.

// Order Type: Represents the type of order, 1:500 yuan deposit user 2,200 yuan deposit user 3 ordinary user
    // pay: indicates whether the user has paid the deposit, true: paid; false: unpaid
    // stock: indicates that the number of mobile phones currently used for ordinary purchases is not restricted by users who have paid the deposit.
   const order = function(orderType,pay,stock){
    if(orderType ==1){
      if(pay === true){
        console.log('500 Pre-purchase with a deposit of $100 and a coupon of $100')
      }else{
        if(stock>0){
          console.log('Ordinary purchase, no coupon')
        }else{
          console.log('Not enough stock to buy')
        }
      }
    }else if(orderType ==2){
      if(pay ===true){
        console.log('200 Pre-purchase with a deposit of $50')
      }else{
        if(stock>0){
          console.log(General purchase,No discount volume)
        }else{
          console.log('Not enough stock to buy')
        }
      }
    }else if( orderType==3){
      if(stock>0){
        console.log('Ordinary purchase, no coupon')
      }else{
        console.log('Not enough inventory to buy')
      }
    }
   }
   order(3,true,500)

Next, the code is revamped with the responsibility chain model:

const order500 = function(orderType,pay,stock){
      if(orderType ===1&&pay==true){
        console.log('500 Pre-purchase with a deposit of $100 and a coupon of $100')
      }else{
        order200(orderType,pay,stock)
      }
    }
    const order200 = function(orderType,pay,stock){
      if(orderType ===2&&pay===true){
        console.log('200 Pre-purchase with a deposit of $50')
      }else{
        orderCommon(orderType,pay,stock)
      }
    }
    const orderCommon = function(orderType,pay,stock){
      if(orderType ===3&&stock>0){
        console.log('Ordinary purchase, no coupon')
      }else{
        console.log('Not enough stock to buy')
      }
    }
    order500(3,true,500)

After modification, it can be found that the code is relatively clear, but the link code and the business code are still coupled together to further optimize:

  const order500 = function(orderType,pay,stock){
    if(orderType ===1 &&pay==true){
      console.log('500 Pre-purchase with a deposit of $100 and a discount of $100')
    }else{
      return 'nextSuccess'
    }
  }
  const order200 = function(orderType,pay,stock){
    if(orderType ===2&&pay===true){
      console.log('200 Pre-purchase with a deposit of $50')
    }else{
      return 'nextSuccess'
    }
  }
  const orderCommon = function(orderType,pay,stock){
    if(orderType==3&&stock>0){
      console.log('Ordinary purchase, no coupon')
    }else{
      console.log('Insufficient stock')
    }
  }
  //Link code
  const chain = function(fn){
    this.fn = fn
    this.successor = null
  }
  chain.prototype.setNext = function(successor){
    this.successor = successor
  }
  chain.prototype.init = function(){
    const result = this.fn.apply(this,arguments)
    if(result == 'nextSuccess'){
      this.successor.init.apply(this.successor,arguments)
    }
  }
  const order500New = new chain(order500)
  const order200New = new chain(order200)
  const orderCommonNew = new chain(orderCommon)
  order500New.setNext(order200New)
  order200New.setNext(orderCommonNew)
  order500New.init(3,true,500)// Ordinary purchases, no coupons

After refactoring, the link code and the business code are completely separated. If we need to add order 300 in the future, we only need to add functions related to it without changing the original business code.

In addition, AOP can simplify the link code mentioned above.

const order500 = function(orderType,pay,stock){
      if(orderType==1&&pay==true){
        console.log('500 Pre-purchase with a deposit of $100 and a coupon of $100')
      }else{
        return 'nextSuccess'
      }
   }
   const order200 = function(orderType,pay,stock){
     if(orderType==2&&pay==true){
       console.log('200 Pre-purchase with a deposit of $50')
     }else{
       return 'nextSuccess'
     }
   }
   const orderCommon = function(orderType,pay,stock){
      if(orderType==3&&stock>0){
        console.log('Ordinary purchase, no coupon')
      }else{
        console.log('Not enough stock to buy')
      }
   }
   Function.prototype.after = function(fn){
     const self = this
     return function(){
       const result = self.apply(self,arguments)
       if(result === 'nextSuccess'){
          return fn.apply(self,arguments)
       }
     }
   }
   const order = order500.after(order200).after(orderCommon)
   order(3,true,500) //Ordinary purchase, no coupon

Posted by jdesilva on Sat, 05 Oct 2019 19:44:13 -0700