This is the fourth day of my participation in Gwen Challenge

First, what is the responsibility chain model

The responsibility chain mode is that when an object A has multiple possible request objects B, C, D and E, we define a responsibility for B, C, D and E respectively to form a responsibility chain. In this way, A only needs to find B to initiate a request, and then continue to request along the responsibility chain until it finds an object to process A.

Girls like to eat together, so I’m looking for someone to eat with. Here’s the code:

B: well… Female programmer is indeed such, eat a meal also want to write code to send request.

const [ astrid, brooke, calliope ] = [{
    name: 'astrid'.requirement: 'I want hunan food'}, {name: 'brooke'.requirement: 'I need 10 people for dinner.'}, {name: 'calliope'.requirement: 'I'm having dinner with my boyfriend.'
}]

// Whether Astrid requirements are met
function isSatisfyAstrid (user) { 
    / /... Omit...
}

// Whether Brooke's requirements are met
function isSatisfyBrooke (user) { 
    / /... Omit...
}

// Whether Calliope requirements are met
function isSatisfyCalliope (user) { 
    / /... Omit...
}

function eatDinner () {
    if (isSatisfyAstrid()) {
        console.log('I can have dinner with Astrid.)}else if (isSatisfyBrooke()) {
        console.log('I can have dinner with Brooke.)}else if (isSatisfyCalliope()) {
        console.log('I can have dinner with calliope.)}else {
        console.log('Oh, I want to have dinner alone.)}}Copy the code

Since Astrid, Brooke, and Calliope had different dinner requests, I needed to make dinner requests one by one until I found someone who agreed to have dinner with me.

Here, I assume that Astrid’s request is to eat Hunan food, Brooke’s request is to have 10 people at a table, and Calliope’s request is to have dinner only with her boyfriend.

The above code is very rigid with if-else, if I have another friend Davi, I have to modify eatDinner method again, which violates open-closed principle and is not easy to maintain.

To optimize the above code, use the chain of responsibilities as follows:

// Define a responsibility for each person
const chainOrderA = new Chain(isSatisfyAstrid)
const chainOrderB = new Chain(isSatisfyBrooke)
const chainOrderC = new Chain(isSatisfyCalliope)

// Set the chain of responsibilities
chainOrderA.setNextSuccessor(chainOrderB)
chainOrderB.setNextSuccessor(chainOrderC)

// To initiate a request, I only need to request the first person on the responsibility chain
function eatDinner () {
    chainOrder.passRequest() // Initiate a request
}
Copy the code

If the responsibilities were turned into the Chain function and the next responsibility function of the responsibility was defined by setNextnextfunction to form a Chain of chainOrderA -> chainOrderB -> chainOrderC responsibility, All I have to do is make a request to Astrid, and if it fails, it will continue along the chain of responsibility until I find someone to have dinner with.

Read on to see how to use the Chain of responsibility pattern and implement the Chain method in a real-world scenario.

Second, the actual scene

1. 618 Pre-sale orders

Next week is 618, e-commerce websites will inevitably launch pre-sale activities, assuming that before 618, 500 yuan deposit, you can get 100 yuan coupon, 200 yuan deposit, you can get 50 coupons, no coupon if you do not pay the deposit. The purchase events on 618 are as follows:

1.1 Common Practices

Code first.

The code in this article is for example only and has nothing to do with business.

Const order = function (orderType) {if (orderType === 500) {console.log(' orderType == 500, } else if (orderType === 200) {console.log(' 200 prepaid, enjoy $50 coupon ')} else {console.log(' No deposit, No discount ')}} order(500)Copy the code

Familiar code, a long if-else judgment, is not conducive to maintenance.

1.2 Responsibility chain mode

Define a responsibility class Chain.

  • Receive a responsibility functionfnAs a parameter;
  • setNextSuccessorSpecify the next responsibility function for this responsibility;
  • passRequestInitiate the responsibility functionfnThe request;
    • If the result is zeronextSuccesstor, indicating that the request fails and continues to request the next responsibility function in the responsibility chain;
    • If it doesn’t returnnextSuccesstorIs found, returns the result of the request, and does not proceed to the next responsibility function in the responsibility chain.

The code is as follows:

const Chain = function(fn) {
  this.fn = fn;
  this.successor = null;
};

Chain.prototype.setNextSuccessor = function(successor) {
  return this.successor = successor;
}

Chain.prototype.passRequest = function() {
  const ret = this.fn.apply(this.arguments)
  if (ret === 'nextSuccessor') {
    return this.successor && this.successor.passRequest.apply(this.successor, arguments);
  }
  return ret;
};
Copy the code

Then define the responsibility class instance to form the chain of responsibility through setnextsucceeded, the code is as follows:

Const order500 = function (orderType) {if (orderType === 500) {console.log(' orderType == 500, Forerunner ')} else {return 'nexttype'}} const order200 = function (orderType) {if (orderType === 200) { Console. log(' 200 deposit paid, Succeeded in $50 coupon ')} else {return 'nextChainOrder500 = new Chain(order500) const chainOrder200 = new Chain(order200) chainOrder500.setNextSuccessor(chainOrder200) chainOrder500.passRequest(200)Copy the code

The above code forms chainOrder500 and chainOrder200 into a chain of responsibilities. Regardless of the user type, all the user needs to do is make a request to chainOrder500. If chainOrder500 cannot process the request, the request will continue along the chain of responsibilities. Until you find a responsible way to handle the request.

The chain of responsibility pattern decouples the complex relationship between request senders and multiple receivers, eliminating the need to know which recipient will receive the sent request and simply making the request to the first stage of the chain of responsibility.

Third, summary

The chain of responsibility pattern helps us manage our code and reduce the coupling between the originating and receiving request objects.

The number and order of nodes in the chain of responsibility pattern can vary freely, allowing you to determine which nodes are included in the chain at run time.

Github source code for practical exercises.

Hope to be helpful to you, thank you for reading ~ don’t forget to click a praise to encourage me oh, pen core ❤️


· Past wonderful ·

Design Patterns – Who hasn’t seen a few singleton patterns (PART 1)

Design Patterns – What is Happy Planet and What is Strategic Pattern (2)

Design Mode – So this is the agent mode (3)

Design Patterns – Easy to Understand Observer Patterns (4)

Design patterns – No, no, there are still people who do not know the decorative pattern (five)

【 Design Patterns – Watch the chain of Responsibility pattern (6) 】