[回到目錄](https://www.cnblogs.com/lori/p/3896484.html) # 責任鏈模式 它是一種設計模塊,主要將操作流程與具體操作解耦,讓每個操作都可以設置自己的操作流程,這對於工作流應用是一個不錯的選擇! 下麵是官方標準的定義:責任鏈模式是一種設計模式。在責任鏈模式 ...
責任鏈模式
它是一種設計模塊,主要將操作流程與具體操作解耦,讓每個操作都可以設置自己的操作流程,這對於工作流應用是一個不錯的選擇!
下麵是官方標準的定義:責任鏈模式是一種設計模式。在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任。
使用場景
責任鏈模式在以下情況下可以被用到:
-
多個對象按照特定順序依次處理請求:當存在多個對象需要依次處理請求,並且每個對象都有可能處理請求或將請求傳遞給下一個對象時,責任鏈模式可以很好地組織和管理這些對象。
-
需要動態指定處理對象:責任鏈模式可以通過動態設置責任鏈的關係,靈活地指定處理對象。可以根據實際情況動態增加、移除或調整處理者的順序,而不需要修改客戶端代碼。
-
避免請求發送者和接收者之間的耦合關係:使用責任鏈模式可以將請求發送者和接收者解耦,發送者只需要將請求發送給責任鏈的第一個處理者,而不需要關心具體是哪個處理者來處理請求。
-
處理請求的對象需要進行動態配置:責任鏈模式可以通過配置文件、資料庫等方式來動態配置處理者的順序和條件,而不需要修改代碼。
-
請求的處理邏輯具有變化和擴展的可能性:責任鏈模式可以很方便地對處理邏輯進行擴展和變化。可以通過增加新的處理者來擴展處理邏輯,也可以通過修改現有處理者的條件判斷來變化處理邏輯。
一些常見的使用場景包括:
- 客戶端請求的處理:比如Web請求處理、日誌記錄、安全認證等。
- 錯誤處理和異常處理:將異常或錯誤從一個處理者傳遞給下一個處理者進行處理,直到找到能夠處理它的處理者。
- 負載均衡:按照一定策略將請求傳遞給多個伺服器進行處理,直到有伺服器能夠處理請求。
- 事件驅動系統:通過觸發事件並將事件傳遞給相關的處理者來實現事件的處理和響應。
需要註意的是,責任鏈模式並不保證一定會有處理者能夠處理請求,因此需要在責任鏈末端進行處理請求無法被處理的情況。
實例中演算法說明
- 每種handler只使用一次
- 按最高優先順序去使用,符合就用,不符合就走下一個策略
- 具體鏈條
- VipHandler >10000
- BigGiftHandler >1000
- DiscountHandler >200
- CouponHandler >100
- DiscountHandler >200
- BigGiftHandler >1000
- VipHandler >10000
代碼實現
- 定義處理請求的介面(Handler):
public interface Handler {
void handleRequest(Order order);
void setNextHandler(Handler nextHandler);
}
- 具體處理請求CouponHandler
public class CouponHandler implements Handler {
private static final Logger logger = LoggerFactory.getLogger(CouponHandler.class);
private Handler nextHandler;
@Override
public void handleRequest(Order order) {
// 這是可以想用多個責任鏈的實現,如果是只使用1個,需要加上200的限制,就是每個訂單隻能現用1種優惠
if (order.getTotalPrice() >= 100) {
// 應用優惠券打9折
order.setTotalPrice(order.getTotalPrice() * .9);
logger.info("Coupon 0.9 applied to order,{}", order.getOrderId());
}else if (nextHandler != null) {
nextHandler.handleRequest(order);
}
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
- 具體處理請求DiscountHandler
public class DiscountHandler implements Handler {
private static final Logger logger = LoggerFactory.getLogger(CouponHandler.class);
private static final double DISCOUNT = .8;
private Handler nextHandler;
@Override
public void handleRequest(Order order) {
if (order.getTotalPrice() >= 200) {
// 應用折扣,折扣為標準的8折
order.setTotalPrice(order.getTotalPrice() * DISCOUNT);
logger.info("Discount 0.8 applied to order,{}", order.getOrderId());
}
else if (nextHandler != null) {
nextHandler.handleRequest(order);
}
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
這個具體命令是可以擴展的,這也是職責鏈(責任鏈)的最重要的體現。
- 命令模式,方便將命令之久,及後期的動態配置
@Data
@AllArgsConstructor
public class HandlerModel implements Comparable<HandlerModel> {
private String title;
private String classPath;
private Integer sort;
@Override
public int compareTo(HandlerModel o) {
return o.getSort() - this.sort; // 降序
}
}
- 命令工廠,這裡使用了強編碼的方式配置命令,真實項目中,這些命令可以配置到資料庫中
/**
* 折扣工廠.
*
* @author lind
* @date 2023/6/28 9:22
* @since 1.0.0
*/
public class HandlerFactory {
public static Handler handlerFactory() {
List<HandlerModel> handlerModels = new ArrayList<>();
handlerModels.add(
new HandlerModel("CouponHandler", "com.lind.common.pattern.chinaorder.handler.CouponHandler", 1));
handlerModels.add(
new HandlerModel("DiscountHandler", "com.lind.common.pattern.chinaorder.handler.DiscountHandler", 2));
handlerModels.add(
new HandlerModel("BigGiftHandler", "com.lind.common.pattern.chinaorder.handler.BigGiftHandler", 3));
handlerModels.add(
new HandlerModel("VipHandler", "com.lind.common.pattern.chinaorder.handler.VipHandler", 4));
return createHandler(handlerModels);
}
private static Handler createHandler(List<HandlerModel> handlerModels) {
Handler handler = null;
Handler previousHandler = null;
for (HandlerModel handlerModel : handlerModels.stream().sorted().collect(Collectors.toList())) {
try {
Handler currentHandler = (Handler) Class.forName(handlerModel.getClassPath()).newInstance();
if (previousHandler != null) {
previousHandler.setNextHandler(currentHandler);
}
else {
handler = currentHandler;
}
previousHandler = currentHandler;
}
catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return handler;
}
}
- 看一下測試的代碼
public static void main(String[] args) {
Handler couponHandler = HandlerFactory.handlerFactory();
Order order1 = new Order("OR01", 150, true);
couponHandler.handleRequest(order1);
logger.info("order1:{}\n", order1.getTotalPrice());
Order order2 = new Order("OR02", 250, true);
couponHandler.handleRequest(order2);
logger.info("order2:{}\n", order2.getTotalPrice());
Order order3 = new Order("OR03", 50, true);
couponHandler.handleRequest(order3);
logger.info("order3:{}\n", order3.getTotalPrice());
Order order4 = new Order("OR04", 5001, true);
couponHandler.handleRequest(order4);
logger.info("order4:{}\n", order4.getTotalPrice());
Order order5 = new Order("OR05", 10001, true);
couponHandler.handleRequest(order5);
logger.info("order5:{}\n", order5.getTotalPrice());
待續……
回到目錄
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!