Detailed explanation of behavioral design model responsibility chain model

Posted by rajeevbharti on Wed, 20 May 2020 07:01:46 +0200

Basic introduction

The chain of Responsibilities Pattern allows you to send the request along the handler chain. After the handler receives the request, he can process it or pass it to the next handler.

Pattern structure

Handler (Abstract handler): defines an interface for processing requests, and aggregates an object (successor) of its own type. Subclass can pass the request on by setting the successor

Concrete handler: after receiving the request, the specific handler can process the request or pass it to the successor.

Request: define some attributes to represent a request

Examples

Company procurement approval process:

  • Amount < = 5000 to be approved by team leader
  • 5000 < amount < = 10000 to be approved by manager
  • Amount > 10000 to be approved by the boss

Request with id and price fields

public class PurchaseRequest {
    private int id;
    private float price;

    public PurchaseRequest(int id, float price) {
        this.id = id;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public float getPrice() {
        return price;
    }
}

Abstract processor

public abstract class Approver {
    protected String name;
    protected Approver approver;

    public Approver(String name) {
        this.name = name;
    }

    public void setApprover(Approver approver) {
        this.approver = approver;
    }

    /**
     * Process request
     * @param request
     */
    public abstract void processRequest(PurchaseRequest request);
}

Specific handler

public class TeamLeader extends Approver {

    public TeamLeader(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getPrice() <= 5000) {
            System.out.println(name + "Approved" + request.getId() + "Request, price is" + request.getPrice());
        } else {
            approver.processRequest(request);
        }
    }
}
public class Manager extends Approver {

    public Manager(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getPrice() > 5000 && request.getPrice() <= 10000) {
            System.out.println(name + "Approved" + request.getId() + "Request, price is" + request.getPrice());
        } else {
            approver.processRequest(request);
        }
    }
}
public class Boss extends Approver {

    public Boss(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getPrice() > 10000) {
            System.out.println(name + "Approved" + request.getId() + "Request, price is" + request.getPrice());
        } else {
            approver.processRequest(request);
        }
    }
}

Test class

public class Client {
    @Test
    public void test(){
        PurchaseRequest request = new PurchaseRequest(1, 5000);

        TeamLeader teamLeader = new TeamLeader("Group leader Li");
        Manager manager = new Manager("Manager Zhang");
        Boss boss = new Boss("Boss Wang");

        teamLeader.setApprover(manager);
        manager.setApprover(boss);
        boss.setApprover(teamLeader);

        manager.processRequest(request);
        boss.processRequest(request);
    }
}

Operation results

Team leader Li approved request No.1 with a price of 5000.0
 Team leader Li approved request No.1 with a price of 5000.0

pattern analysis

advantage

  • Reduce coupling. It decouples the sender and receiver of the request
  • Simplified objects. So that the object does not need to know the structure of the chain
  • Increase flexibility in assigning responsibilities to objects. Allow dynamic addition or deletion of responsibilities by changing the members of the chain or moving their order
  • It is convenient to add new request processing classes

shortcoming

  • There is no guarantee that the request will be received
  • The system performance will be affected to some extent, and it is not convenient to debug the code, which may cause circular calls
  • It may not be easy to observe the characteristics of the running time, which hinders debugging

Applicable scenarios

  • There are multiple objects that can handle the same request. The runtime automatically determines which object handles the request
  • Submit a request to one of multiple objects without explicitly specifying the recipient
  • A set of objects can be dynamically specified to process requests