设计模式-职责链
Author: 图恩Category: 编程开发Views: 687Published: 2022-05-12 **Chain of Responsibility Pattern**
**Introduction**
The Chain of Responsibility Pattern is remarkably similar to Aspect Oriented Programming (AOP) — a design pattern that separates concerns by isolating business logic components. This approach enhances code reusability and development efficiency by reducing interdependencies between business logic components.
**Example**
Consider a scenario where purchasing a phone is determined by the order level:
- **Level 1**: 100 yuan discount coupon if deposit is paid
- **Level 2**: 50 yuan discount coupon if deposit is paid
- **Level 3**: No discount
The code below illustrates this logic:
```javascript
function order(orderType, pay, stock) {
if (orderType === 1) {
if (pay === true) {
console.log("500元定金预购,得到100元优惠券!");
} else {
if (stock > 0) {
console.log("普通购买,无优惠券!");
} else {
console.log("库存不足!");
}
}
} else if (orderType === 2) {
if (pay === true) {
console.log("200元定金预购,得到50元优惠券!");
} else {
if (stock > 0) {
console.log("普通购买,无优惠券!");
} else {
console.log("库存不足!");
}
}
} else {
if (stock > 0) {
console.log("普通购买,无优惠券!");
} else {
console.log("库存不足!");
}
}
}
order(1, true, 10); // 500元定金预购,得到100元优惠券!
order(2, true, 10); // 200元定金预购,得到50元优惠券!
order(3, true, 10); // 普通购买,无优惠券!
order(3, true, 0); // 库存不足!
```
**Code Issues**
The code is clear but verbose, resembling "the old woman's footwraps — long, stinky, and unhelpful." Multiple branches return identical results, leading to repetitive code.
**Refactoring Strategy**
To address this, we abstract the order logic into a chain of handlers:
**Step 1: Abstract Order Objects**
Three order types are defined:
```javascript
var order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log("500元定金预购,得到100元优惠券!");
} else {
return "nextHandler";
}
};
var order200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log("200元定金预购,得到50元优惠券!");
} else {
return "nextHandler";
}
};
var orderNormal = function (orderType, pay, stock) {
if (stock > 0) {
console.log("普通购买,无优惠券!");
} else {
console.log("库存不足!");
}
};
```
**Step 2: Abstract Flow Objects**
A `Chain` class manages the handler sequence:
```javascript
function Chain() {
var fns = Array.prototype.slice.call(arguments);
return function () {
return loop(fns, this, arguments);
};
}
function loop(fns, self, args) {
if (fns.length === 0) {
console.log("缺少Handler");
return;
}
var copyFns = Array.prototype.slice.call(fns);
var res = copyFns.shift().apply(self, args);
if (res === "nextHandler") {
return loop(copyFns, self, args);
} else {
return res;
}
}
```
**Key Insights**
- **Flexibility**: The number of handlers and their order can be dynamically adjusted.
- **Flexibility**: Handler types can vary as long as the interface is consistent (duck typing).
- **Principle**: The design follows the "Open/Closed Principle" — new handlers can be added without modifying existing code.
**Conclusion**
The Chain of Responsibility Pattern allows for dynamic composition of handlers. While the number of handlers can vary, their order and types can be flexibly managed. Handlers can handle different responsibilities as long as they conform to the same interface. This approach balances flexibility with maintainability.