Analysis of Objective-C design pattern – responsibility chain

Time:2020-5-27

Pattern of picture reading

Let’s take a process at work as an example. Although it has been abused, I think it’s just right for today’s model.

For example, one of the employees of the company, Xiao a, recently performed well, worked hard and solved problems efficiently, so Xiao a wanted to raise his salary. But the company’s management sequence is responsible. What should we do?

Analysis of Objective-C design pattern - responsibility chain

First of all, Xiao a found the Department Manager directly under her, but the department manager said that I had no authority.
Next, Xiao a goes to the Department Director, who also says he has no authority;
Finally, little a found the general manager, who agreed to a’s request after careful investigation.

analysis

In the above process, there is a problem: employee a needs to know multiple managers and everyone in the management sequence. And it takes a lot of result judgment, which leads tocoupling

Or we don’t set up so many managers, only one is not enough, let it deal with all management problems. Certainly not in reality (can be exhausted to death ~), but the code runs well. However, this is not in line withSingle responsibilityIn addition, to add new management functions, you need to override this class, which is also inconsistent with theOpen closed principle

Through the above situation, we can summarize two laws:

  • The process is a chain, which needs to be handled at the level of each manager.
  • Once a manager is able to handle the problem, the request is over and there is no need to find the next manager.

solve

We can design this way to let each manager add a point of next handler, which is his superior. When he receives a request, he will judge whether he has permission to process it. If he does not have permission, he will pass the request to the next handler. If he has permission, he will process the request and end the delivery. Each of the latter processors repeats the same operation.

This is the relationship between managers:

Analysis of Objective-C design pattern - responsibility chain

The processing flow of the problem is as follows:

Analysis of Objective-C design pattern - responsibility chain

In fact, the real workflow or online BPM management uses this method, which isResponsibility chain model

Schema definition

definition

Responsibility chain pattern: it enables multiple objects to process requests, so as to avoid coupling between the sender and the receiver of requests. This pattern links these objects into a chain and passes the request along the chain until an object processes it.

The main idea of the responsibility chain model is that an object refers to another object of the same type to form a chain. Each object in the chain implements the same method, processing the same request for the first object in the chain. If an object does not know how to handle the request, it passes the request to the next responder

Class structure diagram

Analysis of Objective-C design pattern - responsibility chain

The responsibility chain model includes the following roles:

Handler (Abstract handler):Defines an interface for processing requests, which is generally designed as an abstract class. Because each handler’s next home is still a handler, an abstract handler type object is defined in the abstract handler as its reference to the next home. With this reference, processors can be linked into a chain.

ConcreteHandler:In the concrete handler class, the abstract request processing method defined in the abstract handler is implemented. Before processing the request, it needs to judge whether there is corresponding processing authority. If it can process the request, it needs to process it, otherwise, it will forward the request to the successor;

code

According to the above definition, see how to implement it in the code:

Write a request class first, which is the object to be processed in the specific processor later. It is written according to your business and has no fixed format. Here is an example

@interface Request : NSObject

@property (nonatomic, copy)NSString *type;
@property (nonatomic, assign)NSUInteger number;

@end

@implementation Request

@end

Handler (Abstract handler), in this case, manager manager

@interface Manager : NSObject

@property (nonatomic, strong) Manager *nextManager;

- (void)handleRequest:(Request *)quest;

@end

@implementation Manager

- (void)handleRequest:(Request *)quest
{
    [self.nextManager handleRequest:quest];
}

@end

Abstract manager has a reference to the lower level processor. The default processing method is to forward the request to the next level processor.

ConcreteHandler: there are three corresponding processors, namely Department Manager, department director and general manager.

Department Manager, can handle leave less than 5 days

@interface DepartmentManager : Manager

@end

@implementation DepartmentManager

- (void)handleRequest:(Request *)quest
{
    if ([ quest.type  Isequaltostring: @ "leave"]&& quest.number  < 5) {
        Nslog (@ '% @: Processed% @,% @, nsstringfromclass ([self class]), quest.type , @( quest.number );
    } else {
        Nslog (@ '% @: not authorized to process% @,% @, nsstringfromclass ([self class]), quest.type , @( quest.number );
        [self.nextManager handleRequest:quest];
    }
}

@end

Department director category, which can handle more than 5 days of leave and job transfer

@interface DepartmentDirector : Manager

@end

@implementation DepartmentDirector

- (void)handleRequest:(Request *)quest
{
    if ([ quest.type  Isequaltostring: @ "transfer"] | ([ quest.type  Isequaltostring: @ "leave"]&& quest.number  > 5)) {
        Nslog (@ '% @: Processed% @,% @, nsstringfromclass ([self class]), quest.type , @( quest.number );
    } else {
        Nslog (@ '% @: not authorized to process% @,% @, nsstringfromclass ([self class]), quest.type , @( quest.number );
        [self.nextManager handleRequest:quest];
    }
}

@end

General manager: can handle salary increase request within 5000

@interface GeneralManager : Manager

@end

@implementation GeneralManager

- (void)handleRequest:(Request *)quest
{
    if ([ quest.type  Isequaltostring: @ "raise salary"]&& quest.number  < 5000) {
        Nslog (@ '% @: Processed% @,% @, nsstringfromclass ([self class]), quest.type , @( quest.number );
    } else {
        Nslog (@ '% @: not authorized to process% @,% @, nsstringfromclass ([self class]), quest.type , @( quest.number );
        [self.nextManager handleRequest:quest];
    }
}

@end

Client call

DepartmentManager *departmentManager = [[DepartmentManager alloc] init];
    DepartmentDirector *departmentDirector = [[DepartmentDirector alloc] init];
    GeneralManager *generalManager = [[GeneralManager alloc] init];
    departmentManager.nextManager = departmentDirector;
    departmentDirector.nextManager = generalManager;
    
    Request *quest1 = [[Request alloc] init];
    Request1. Type = @ "increase salary";
    quest1.number = 1000;
    [departmentManager handleRequest:quest1];
    
    Request *quest2 = [[Request alloc] init];
    Request2. Type = @ "leave";
    quest2.number = 10;
    [departmentManager handleRequest:quest2];

Operation results

Analysis of Objective-C design pattern - responsibility chain

Employees do not need to care about the delivery and processing of subsequent processing requests after they send them. The request will eventually flow to the manager who can handle it.

The processor in the responsibility chain is responsible for processing the request. The customer only needs to send the request to the responsibility chain, and does not need to care about the processing details of the request and the transmission of the request. Therefore, the responsibility chain decouples the sender of the request and the processor of the request.

The client issuing the request here does not know which of these objects will finally process the request, so that the system changes can dynamically reorganize and allocate responsibilities without affecting the client.

For example, when the company's management sequence changes and a president is added, we only need to add the manager in the chain,
Don't care about the originator of the request. This structure is a one-way linked list structure. It also has the dynamic flexibility of adding and deleting.

features

flexibility

Where is the flexibility of responsibility chain

  • Change internal delivery rules

    Internally, the project manager can skip the personnel department to find the general manager directly. Everyone can dynamically assign his or her successor.
  • You can start at any level of the responsibility chain.

    If the project manager is not available, you can go to the Department Manager directly, and the responsibility chain will continue without any influence.
  • The difference between using and not using

    Instead of having a responsibility chain structure, we need to have a coupling relationship with every level in the company.
    If reflected in the code, even if we need to write a lot of ugly if in a class . else statement.
    If we use the responsibility chain, it is equivalent to facing a black box. We only need to know one of the departments,
    Then let the inside of the black box be responsible for the delivery

objective

Avoid coupling the sender and receiver of the request, make it possible for multiple objects to receive the request, connect these objects into a chain, and pass the request along the chain until there is an object to process it.

Use scenario

  • There are multiple objects that can handle requests, and the handler can only determine at run time.
  • Makes a request to a set of objects without displaying the specific handler that specified the request to be processed.

Advantages and disadvantages

advantage

  • The responsibility chain mode makes an object do not need to know which other object processes its request. The object only needs to know that the request will be processed. Neither the receiver nor the sender has the clear information of the other party, and the object in the chain does not need to know the structure of the chain. The client is responsible for the creation of the chain, which reduces the coupling degree of the system.
  • The request processing object only needs to maintain a reference to its successor, and does not need to maintain its reference to all candidate processors, which can simplify the interconnection of objects.
  • When assigning responsibility to an object, the responsibility chain can give us more flexibility. We can add or change the responsibility of processing a request by dynamically adding or modifying the chain at runtime.
  • Adding a new specific request handler to the system does not need to modify the original system code, but only needs to rebuild the chain on the client side, which is in line with the “open close principle”.

shortcoming

  • Because a request has no clear receiver, the request may not be processed all the way to the end of the chain; a request may not be processed because the responsibility chain is not properly configured.
  • For a relatively long responsibility chain, the processing of the request may involve multiple processing objects, and the system performance will be affected to some extent, and it is not convenient for code debugging.
  • If the chain is not built properly, it may cause a circular call, which will cause the system to fall into a dead cycle.