二十:职责链模式详解(类似于spring的hangler处理请求)
定義:為了避免請求的發送者和接收者之間的耦合關系,使多個接受對象都有機會處理請求。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
“看這個定義,就是將一堆可以處理請求的對象連成一條鏈,然后一個一個試著處理請求。這好像是可以解決麥當勞訂餐的問題的,我先來看看我剛才苦B的訂餐過程是什么樣子的。” “首先應該有一個麥當勞的分店的類,它的主要功能是可以訂餐。”
“先來看看職責鏈模式的類圖,這樣比較好設計。”
“類圖還是比較簡單的啊,有一個通用的接口,然后就是若干個具體的處理者。按照現在麥當勞的情況來說,接口里handleRequest方法其實就是order(訂餐)方法了,而setSuccessor方法,則是用來設置職責鏈的下一個處理者。”
“對于麥當勞的問題來說,每一個分店就是具體的處理者了,主要的改動應該是抽象出來一個接口以及職責鏈的連接過程,而剛才發送訂單的時候是拆分成方法參數傳遞給訂餐方法的,現在最好是把訂單做成一個數據類。”
package com.chain; import java.util.Map; //訂單類(相當于request,其實就是封裝一個請求)
public class Order { private int x;
private int y;
private Map<String, Integer> order; public Order(int x, int y, Map<String, Integer> order) {
super();
this.x = x;
this.y = y;
this.order = order;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
} public Map<String, Integer> getOrder() {
return order;
} public void setOrder(Map<String, Integer> order) {
this.order = order;
} }
“下面便應該是分店接口了,它有兩個方法,和類圖當中的方法類似,只是名稱略有改變。”
package com.chain;
//分店接口(相當于Hanlder)
public interface Subbranch { void setSuccessor(Subbranch subbranch); boolean handleOrder(Order order); }
“下面便是麥當勞分店的實現類了,它主要的改變是添加了一個屬性(下一個分店),這應該就是鏈形成的基石了。”
package com.chain; import java.util.Collections;
import java.util.Map; //麥當勞分店
public class McSubbranch implements Subbranch{ private final static int MIN_DISTANCE = 500;//假設是500米以內送餐 private static int count;//類計數 private final int number;//分店號 private int x;//分店的橫坐標,用于判斷距離 private int y;//分店的縱坐標,用于判斷距離 private Map<String, Integer> menu;//菜單 private Subbranch nextSubbranch;//下一家分店 public McSubbranch(int x, int y, Map<String, Integer> menu) {
super();
this.x = x;
this.y = y;
this.menu = menu;
number = ++count;
}
//設置下一家分店
public void setSuccessor(Subbranch subbranch) {
this.nextSubbranch = subbranch;
}
//按照職責鏈處理訂單
public boolean handleOrder(Order order){
//如果距離小于500米并且訂單中的食物不缺貨,則訂單成功,否則失敗
if (CommonUtils.getDistance(order.getX(), order.getY(), this.x, this.y) < MIN_DISTANCE && !CommonUtils.outOfStock(menu, order.getOrder())) {
for (String name : order.getOrder().keySet()) {
menu.put(name, menu.get(name) - order.getOrder().get(name));
}
System.out.println("訂餐成功,接受訂單的分店是:" + this);
return true;
}
if (nextSubbranch == null) {
return false;
}
return nextSubbranch.handleOrder(order);
} public Map<String, Integer> getMenu() {
return Collections.unmodifiableMap(menu);
} public Subbranch getNextSubbranch() {
return nextSubbranch;
} public String toString() {
return "麥當勞分店第" + number + "個";
} }
“handleOrder方法中的邏輯就是職責鏈的精髓了,它會試圖處理請求,如果處理不了,則交給鏈中的下一個分店。剛才用的CommonUtils應該不用變了。下面就看下有了職責鏈模式之后,我的訂餐方式吧。”
package com.chain; import java.util.HashMap;
import java.util.Map; public class Client { public static void main(String[] args) {
//假設初始菜單都是以下這些東西
Map<String, Integer> menu = new HashMap<String, Integer>();
menu.put("漢堡", 5);
menu.put("薯條", 5);
menu.put("可樂", 5);
menu.put("雪碧", 5);
//假設有5個分店
Subbranch mcSubbranch1 = new McSubbranch(0, 0, new HashMap<String, Integer>(menu));
Subbranch mcSubbranch2 = new McSubbranch(100, 120, new HashMap<String, Integer>(menu));
Subbranch mcSubbranch3 = new McSubbranch(-100, -120, new HashMap<String, Integer>(menu));
Subbranch mcSubbranch4 = new McSubbranch(1000, 20, new HashMap<String, Integer>(menu));
Subbranch mcSubbranch5 = new McSubbranch(-500, 0, new HashMap<String, Integer>(menu)); //以下設置職責鏈
mcSubbranch4.setSuccessor(mcSubbranch5);
mcSubbranch3.setSuccessor(mcSubbranch4);
mcSubbranch2.setSuccessor(mcSubbranch3);
mcSubbranch1.setSuccessor(mcSubbranch2);
//小左開始訂餐,假設小左的坐標是900,20
Map<String, Integer> order = new HashMap<String, Integer>();
order.put("漢堡", 2);
order.put("可樂", 1);
order.put("薯條", 1); print(mcSubbranch1);
System.out.println("------------------------------------------"); //小左開始訂餐,直接找mcSubbranch1的這一家分店訂餐即可
mcSubbranch1.handleOrder(new Order(900, 20, order)); System.out.println("------------------------------------------");
print(mcSubbranch1);
} public static void print(Subbranch subbranch){
if (subbranch == null ) {
return;
}
do {
if (subbranch instanceof McSubbranch) {
System.out.println("[" + subbranch + "]的菜單:" + ((McSubbranch) subbranch).getMenu());
}
} while ((subbranch = ((McSubbranch) subbranch).getNextSubbranch()) != null);
} }
“輸出結果和剛才是一樣的,不過這下我訂餐就好辦多了,直接找第一家分店訂餐就行,至于到最后誰給我送餐,我就不用管了。”
1、客戶端與具體的處理者解耦,客戶端只認識一個Hanlder接口,降低了客戶端(即請求發送者)與處理者的耦合度。
2、客戶端和處理者都不關心職責鏈的具體結構,而是交給職責鏈的創造者(在上述例子當中則是交給了OrderManager),也正因為如此,當在職責鏈中添加處理者的時候,這對客戶端和處理者來說,都是透明的,二者不知道也不必要知道職責鏈的變化。
總結
以上是生活随笔為你收集整理的二十:职责链模式详解(类似于spring的hangler处理请求)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python的zip函数(转)
- 下一篇: MacBook使用HHKB键盘设置