introduce
Chain of responsibility is to enable multiple objects to have the opportunity to process the request, thereby avoiding the coupling relationship between the sender and the receiver of the request. Connect the object into a chain and pass the request along the chain until an object handles it.
That is, after the request, starting from the first object, the object receiving the request in the chain either handles it personally or forwards it to the next candidate in the chain. The object submitting the request does not know exactly which object will handle it - that is, the request has an implicit receiver. Depending on the run time, any candidate can respond to the corresponding request. The number of candidates is arbitrary. You can decide which candidates participate in the chain at the run time.
text
For JavaScript implementations, we can use its prototype features to implement the responsibility chain pattern.
The code copy is as follows:
var NO_TOPIC = -1;
var Topic;
function Handler(s, t) {
this.successor = s || null;
this.topic = t || 0;
}
Handler.prototype = {
handle: function () {
if (this.successor) {
this.successor.handle()
}
},
has: function () {
return this.topic != NO_TOPIC;
}
};
The Handler just accepts 2 parameters. The first is the successor (used to pass the processing request down), and the second is the passing level (which can be used to control whether to perform an operation at a certain level, or not). The Handler prototype exposes a handle method, which is the key to implementing this pattern. Let's first look at how to use the above code.
The code copy is as follows:
var app = new Handler({
handle: function () {
console.log('app handle');
}
}, 3);
var dialog = new Handler(app, 1);
var button = new Handler(dialog, 2);
button.handle();
Change the code through the prototype feature and call the code from button.handle()->dialog.handle()->app.handle()->parameter handle(). The first three are all the handles that call the prototype. Finally, the handle in the passed parameter is found, and then the result is output, which means that only the last layer is processed.
So how can I only let the dialog object be processed when calling? In fact, you can define the handle method of the dialog instance object, but it needs to be done before the new button. The code is as follows:
The code copy is as follows:
var app = new Handler({
handle: function () {
console.log('app handle');
}
}, 3);
var dialog = new Handler(app, 1);
dialog.handle = function () {
console.log('dialog before...')
// Here are the specific processing operations
console.log('dialog after ...')
};
var button = new Handler(dialog, 2);
button.handle();
The execution result of this code is the process result in the dialog.handle, and is no longer the execution operation of the handle defined in the parameters passed to the app.
So can we make it through the process of the successor and then let the successor continue to handle it? The answer is yes, but after calling the handle, you need to use the characteristics of the prototype to call the following code:
The code copy is as follows:
Handler.prototype.handle.call(this);
The meaning of this sentence is to call the prototype handle method to continue calling the handle method of its successor (that is, successor). The following code is expressed as: the handles defined by the three objects of button/dialog/app will be executed.
The code copy is as follows:
var app = new Handler({
handle: function () {
console.log('app handle');
}
}, 3);
var dialog = new Handler(app, 1);
dialog.handle = function () {
console.log('dialog before...')
// Here are the specific processing operations
Handler.prototype.handle.call(this); //Continue to go up
console.log('dialog after ...')
};
var button = new Handler(dialog, 2);
button.handle = function () {
console.log('button before...')
// Here are the specific processing operations
Handler.prototype.handle.call(this);
console.log('button after ...')
};
button.handle();
Through the running results of the code, we can see that if you want to process it yourself first and then call the successor to process it, execute the Handler.prototype.handle.call(this); code at the end. If you want to process the successor's code first, execute the Handler.prototype.handle.call(this); code at the beginning.
Summarize
The chain of responsibilities is often used with the combination pattern, so that the parent component of a component can serve as its successor.
At the same time, the event bubble mechanism in the DOM seems to be a bit similar to this. For example, after clicking a button, if the bubble is not prevented, the click event will always bubble towards the parent element. This mechanism can also be used to deal with many related problems, such as the example code of "Example 1: Centralized Event Management" in the design pattern of this series.