java設計模式總結(三) ---- 十一種行為型模式
1 模板方法模式
理解:把執行過程的方法按照一定的順序進行放在同一個方法中,對這些過程進行統一管理
再用一個案例來說明一下:
package com.atguigu.template; //抽象類,表示豆漿 public abstract class SoyaMilk { //模板方法, make , 模板方法可以做成final , 不讓子類去覆蓋. final void make() { select(); addCondiments(); soak(); beat(); }//選材料 void select() { System.out.println("第一步:選擇好的新鮮黃豆 "); } //新增不同的配料, 抽象方法, 子類具體實現 abstract void addCondiments(); //浸泡 void soak() { System.out.println("第三步, 黃豆和配料開始浸泡, 需要3小時 "); } void beat() { System.out.println("第四步:黃豆和配料放到豆漿機去打碎 "); } }
配料類:
package com.atguigu.template; public class PeanutSoyaMilk extends SoyaMilk { @Override void addCondiments() { // TODO Auto-generated method stub System.out.println(" 加入上好的花生 "); } }
模板方法在Spring中的使用:
2命令模式
我們在軟體設計時,對於請求者來說我們只需要知道我們的請求(命令者)和響應(接受者)即可,其他細節我們不需要了解其細節
例項:實現對於家電控制的模擬
對於命令介面的實現:
package com.atguigu.command; import java.util.Arrays; //建立命令介面 public interface Command { //執行動作(操作) public void execute(); //撤銷動作(操作) public void undo(); }
實現具體的傢俱:
package com.atguigu.command; public class LightReceiver { public void on() { System.out.println(" 電燈打開了.. "); } public void off() { System.out.println(" 電燈關閉了.. "); } }
空命令的初始化:
package com.atguigu.command; /** * 沒有任何命令,即空執行: 用於初始化每個按鈕, 當呼叫空命令時,物件什麼都不做 * 其實,這樣是一種設計模式, 可以省掉對空判斷 * @author Administrator * */ public class NoCommand implements Command { @Override public void execute() { // TODO Auto-generated method stub } @Override public void undo() { // TODO Auto-generated method stub } }
子類對於命令的具體實現(還有一個關燈方法類似):
package com.atguigu.command; public class LightOnCommand implements Command { //聚合LightReceiver LightReceiver light; //構造器 public LightOnCommand(LightReceiver light) { super(); this.light = light; } @Override public void execute() { // TODO Auto-generated method stub //呼叫接收者的方法 light.on(); } @Override public void undo() { // TODO Auto-generated method stub //呼叫接收者的方法 light.off(); } }
命令模式 在Spring--JDBCTemplate中的運用
個人感覺:這裡和建造者模式有一點相似。
3訪問者模式
目的:將資料結構和資料的操作進行分離。
我們用一個使用者對於評價歌手的案例來看:
package com.atguigu.visitor; public abstract class Action { //得到男性 的測評 public abstract void getManResult(Man man); //得到女的 測評 public abstract void getWomanResult(Woman woman); }
package com.atguigu.visitor; public abstract class Person { //提供一個方法,讓訪問者可以訪問 public abstract void accept(Action action); }
package com.atguigu.visitor; import java.util.LinkedList; import java.util.List; //資料結構,管理很多人(Man , Woman) public class ObjectStructure { //維護了一個集合 private List<Person> persons = new LinkedList<>(); //增加到list public void attach(Person p) { persons.add(p); } //移除 public void detach(Person p) { persons.remove(p); } //顯示測評情況 public void display(Action action) { for(Person p: persons) { p.accept(action); } } }
4迭代器模式
類比於集合中的迭代器,迭代器模式就是對於集合或者陣列中的元素進行遍歷。
讓類去繼承Iterator
迭代器模式在JDK中ArrayList中的使用
5觀察者模式
當物件間存在一對多關係時,則使用觀察者模式(Observer Pattern)。比如,當一個物件被修改時,則會自動通知依賴它的物件
當一個類改變時,其他類都會得知他的改變,我們來看一個案例,天氣
觀察者就是在Weather天氣類改變的時候,去遍歷所有類並讓他們發生變化
package com.atguigu.observer.improve; import java.util.ArrayList; /** * 類是核心 * 1. 包含最新的天氣情況資訊 * 2. 含有 觀察者集合,使用ArrayList管理 * 3. 當資料有更新時,就主動的呼叫 ArrayList, 通知所有的(接入方)就看到最新的資訊 * @author Administrator * */ public class WeatherData implements Subject { private float temperatrue; private float pressure; private float humidity; //觀察者集合 private ArrayList<Observer> observers; //加入新的第三方 public WeatherData() { observers = new ArrayList<Observer>(); } public float getTemperature() { return temperatrue; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } public void dataChange() { //呼叫 接入方的 update notifyObservers(); } //當資料有更新時,就呼叫 setData public void setData(float temperature, float pressure, float humidity) { this.temperatrue = temperature; this.pressure = pressure; this.humidity = humidity; //呼叫dataChange, 將最新的資訊 推送給 接入方 currentConditions dataChange(); } //註冊一個觀察者 @Override public void registerObserver(Observer o) { // TODO Auto-generated method stub observers.add(o); } //移除一個觀察者 @Override public void removeObserver(Observer o) { // TODO Auto-generated method stub if(observers.contains(o)) { observers.remove(o); } } //遍歷所有的觀察者,並通知 @Override public void notifyObservers() { // TODO Auto-generated method stub for(int i = 0; i < observers.size(); i++) { observers.get(i).update(this.temperatrue, this.pressure, this.humidity); } } }
具體使用類:
package com.atguigu.observer.improve; public class BaiduSite implements Observer { // 溫度,氣壓,溼度 private float temperature; private float pressure; private float humidity; // 更新 天氣情況,是由 WeatherData 來呼叫,我使用推送模式 public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } // 顯示 public void display() { System.out.println("===百度網站===="); System.out.println("***百度網站 氣溫 : " + temperature + "***"); System.out.println("***百度網站 氣壓: " + pressure + "***"); System.out.println("***百度網站 溼度: " + humidity + "***"); } }
觀察者模式在JDK中Obsreve中的使用:
6 中介者模式
用一箇中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。
由一對多變成了一對一
中介者模式對於家庭電器的管理:
分析一下中介者的程式碼:
將所有需要操作的物件都放入進來,根據Register方法判斷放入HashMap中的key的值是什麼,然後value放入對應的值
再GetMessage傳入進來的類名,取出對應的類執行相關操作
ps:該類一旦出現問題,整個系統都將癱瘓
package com.atguigu.mediator.smarthouse; import java.util.HashMap; //具體的中介者類 public class ConcreteMediator extends Mediator { //集合,放入所有的同事物件 private HashMap<String, Colleague> colleagueMap; private HashMap<String, String> interMap; public ConcreteMediator() { colleagueMap = new HashMap<String, Colleague>(); interMap = new HashMap<String, String>(); } @Override public void Register(String colleagueName, Colleague colleague) { // TODO Auto-generated method stub colleagueMap.put(colleagueName, colleague); // TODO Auto-generated method stub if (colleague instanceof Alarm) { interMap.put("Alarm", colleagueName); } else if (colleague instanceof CoffeeMachine) { interMap.put("CoffeeMachine", colleagueName); } else if (colleague instanceof TV) { interMap.put("TV", colleagueName); } else if (colleague instanceof Curtains) { interMap.put("Curtains", colleagueName); } } //具體中介者的核心方法 //1. 根據得到訊息,完成對應任務 //2. 中介者在這個方法,協調各個具體的同事物件,完成任務 @Override public void GetMessage(int stateChange, String colleagueName) { // TODO Auto-generated method stub //處理鬧鐘發出的訊息 if (colleagueMap.get(colleagueName) instanceof Alarm) { if (stateChange == 0) { ((CoffeeMachine) (colleagueMap.get(interMap .get("CoffeeMachine")))).StartCoffee(); ((TV) (colleagueMap.get(interMap.get("TV")))).StartTv(); } else if (stateChange == 1) { ((TV) (colleagueMap.get(interMap.get("TV")))).StopTv(); } } else if (colleagueMap.get(colleagueName) instanceof CoffeeMachine) { ((Curtains) (colleagueMap.get(interMap.get("Curtains")))) .UpCurtains(); } else if (colleagueMap.get(colleagueName) instanceof TV) {//如果TV發現訊息 } else if (colleagueMap.get(colleagueName) instanceof Curtains) { //如果是以窗簾發出的訊息,這裡處理... } } @Override public void SendMessage() { // TODO Auto-generated method stub } }
7備忘錄模式
記錄狀態情況,舉一個遊戲例子
這是一個遊戲角色的基本狀態:
package com.atguigu.memento.game; public class Memento { //攻擊力 private int vit; //防禦力 private int def; public Memento(int vit, int def) { super(); this.vit = vit; this.def = def; } public int getVit() { return vit; } public void setVit(int vit) { this.vit = vit; } public int getDef() { return def; } public void setDef(int def) { this.def = def; } }
這是一個遊戲角色備忘錄:
package com.atguigu.memento.game; public class Memento { //攻擊力 private int vit; //防禦力 private int def; public Memento(int vit, int def) { super(); this.vit = vit; this.def = def; } public int getVit() { return vit; } public void setVit(int vit) { this.vit = vit; } public int getDef() { return def; } public void setDef(int def) { this.def = def; } }
守護者,儲存狀態:
package com.atguigu.memento.game;
import java.util.ArrayList;
import java.util.HashMap;
//守護者物件, 儲存遊戲角色的狀態
public class Caretaker {
//如果只儲存一次狀態
private Memento memento;
//對GameRole 儲存多次狀態
//private ArrayList<Memento> mementos;
//對多個遊戲角色儲存多個狀態
//private HashMap<String, ArrayList<Memento>> rolesMementos;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
這就是備忘錄模式
8直譯器模式
直譯器模式是對於一長串的字串進行的拆解.
package com.atguigu.interpreter; import java.util.HashMap; /** * 加法直譯器 * @author Administrator * */ public class AddExpression extends SymbolExpression { public AddExpression(Expression left, Expression right) { super(left, right); } //處理相加 //var 仍然是 {a=10,b=20}.. //一會我們debug 原始碼,就ok public int interpreter(HashMap<String, Integer> var) { //super.left.interpreter(var) : 返回 left 表示式對應的值 a = 10 //super.right.interpreter(var): 返回right 表示式對應值 b = 20 return super.left.interpreter(var) + super.right.interpreter(var); } }
package com.atguigu.interpreter; import java.util.HashMap; import java.util.Stack; public class Calculator { // 定義表示式 private Expression expression; // 建構函式傳參,並解析 public Calculator(String expStr) { // expStr = a+b // 安排運算先後順序 Stack<Expression> stack = new Stack<>(); // 表示式拆分成字元陣列 char[] charArray = expStr.toCharArray();// [a, +, b] Expression left = null; Expression right = null; //遍歷我們的字元陣列, 即遍歷 [a, +, b] //針對不同的情況,做處理 for (int i = 0; i < charArray.length; i++) { switch (charArray[i]) { case '+': // left = stack.pop();// 從stack取出left => "a" right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表示式 "b" stack.push(new AddExpression(left, right));// 然後根據得到left 和 right 構建 AddExpresson加入stack break; case '-': // left = stack.pop(); right = new VarExpression(String.valueOf(charArray[++i])); stack.push(new SubExpression(left, right)); break; default: //如果是一個 Var 就建立要給 VarExpression 物件,並push到 stack stack.push(new VarExpression(String.valueOf(charArray[i]))); break; } } //當遍歷完整個 charArray 陣列後,stack 就得到最後Expression this.expression = stack.pop(); } public int run(HashMap<String, Integer> var) { //最後將表示式a+b和 var = {a=10,b=20} //然後傳遞給expression的interpreter進行解釋執行 return this.expression.interpreter(var); } }
package com.atguigu.interpreter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; public class ClientTest { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub String expStr = getExpStr(); // a+b HashMap<String, Integer> var = getValue(expStr);// var {a=10, b=20} Calculator calculator = new Calculator(expStr); System.out.println("運算結果:" + expStr + "=" + calculator.run(var)); } // 獲得表示式 public static String getExpStr() throws IOException { System.out.print("請輸入表示式:"); return (new BufferedReader(new InputStreamReader(System.in))).readLine(); } // 獲得值對映 public static HashMap<String, Integer> getValue(String expStr) throws IOException { HashMap<String, Integer> map = new HashMap<>(); for (char ch : expStr.toCharArray()) { if (ch != '+' && ch != '-') { if (!map.containsKey(String.valueOf(ch))) { System.out.print("請輸入" + String.valueOf(ch) + "的值:"); String in = (new BufferedReader(new InputStreamReader(System.in))).readLine(); map.put(String.valueOf(ch), Integer.valueOf(in)); } } } return map; } }
package com.atguigu.interpreter; import java.util.HashMap; /** * 抽象類表示式,通過HashMap 鍵值對, 可以獲取到變數的值 * * @author Administrator * */ public abstract class Expression { // a + b - c // 解釋公式和數值, key 就是公式(表示式) 引數[a,b,c], value就是就是具體值 // HashMap {a=10, b=20} public abstract int interpreter(HashMap<String, Integer> var); }
package com.atguigu.interpreter; import java.util.HashMap; public class SubExpression extends SymbolExpression { public SubExpression(Expression left, Expression right) { super(left, right); } //求出left 和 right 表示式相減後的結果 public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) - super.right.interpreter(var); } }
package com.atguigu.interpreter; import java.util.HashMap; /** * 抽象運算子號解析器 這裡,每個運算子號,都只和自己左右兩個數字有關係, * 但左右兩個數字有可能也是一個解析的結果,無論何種型別,都是Expression類的實現類 * * @author Administrator * */ public class SymbolExpression extends Expression { protected Expression left; protected Expression right; public SymbolExpression(Expression left, Expression right) { this.left = left; this.right = right; } //因為 SymbolExpression 是讓其子類來實現,因此 interpreter 是一個預設實現 @Override public int interpreter(HashMap<String, Integer> var) { // TODO Auto-generated method stub return 0; } }
package com.atguigu.interpreter; import java.util.HashMap; /** * 變數的直譯器 * @author Administrator * */ public class VarExpression extends Expression { private String key; // key=a,key=b,key=c public VarExpression(String key) { this.key = key; } // var 就是{a=10, b=20} // interpreter 根據 變數名稱,返回對應值 @Override public int interpreter(HashMap<String, Integer> var) { return var.get(this.key); } }
直譯器模式在SpelExpressionParser中的使用
9狀態模式
每一個黃色的框框就代表一種狀態
用不同的狀態來表示相應的情況
宣告一個狀態介面:
package com.atguigu.state; /** * 狀態抽象類 * @author Administrator * */ public abstract class State { // 扣除積分 - 50 public abstract void deductMoney(); // 是否抽中獎品 public abstract boolean raffle(); // 發放獎品 public abstract void dispensePrize(); }
四種類型繼承該狀態:
package com.atguigu.state; /** * 不能抽獎狀態 * @author Administrator * */ public class NoRaffleState extends State { // 初始化時傳入活動引用,扣除積分後改變其狀態 RaffleActivity activity; public NoRaffleState(RaffleActivity activity) { this.activity = activity; } // 當前狀態可以扣積分 , 扣除後,將狀態設定成可以抽獎狀態 @Override public void deductMoney() { System.out.println("扣除50積分成功,您可以抽獎了"); activity.setState(activity.getCanRaffleState()); } // 當前狀態不能抽獎 @Override public boolean raffle() { System.out.println("扣了積分才能抽獎喔!"); return false; } // 當前狀態不能發獎品 @Override public void dispensePrize() { System.out.println("不能發放獎品"); } }
package com.atguigu.state; /** * 發放獎品的狀態 * @author Administrator * */ public class DispenseState extends State { // 初始化時傳入活動引用,發放獎品後改變其狀態 RaffleActivity activity; public DispenseState(RaffleActivity activity) { this.activity = activity; } // @Override public void deductMoney() { System.out.println("不能扣除積分"); } @Override public boolean raffle() { System.out.println("不能抽獎"); return false; } //發放獎品 @Override public void dispensePrize() { if(activity.getCount() > 0){ System.out.println("恭喜中獎了"); // 改變狀態為不能抽獎 activity.setState(activity.getNoRafflleState()); }else{ System.out.println("很遺憾,獎品傳送完了"); // 改變狀態為獎品傳送完畢, 後面我們就不可以抽獎 activity.setState(activity.getDispensOutState()); //System.out.println("抽獎活動結束"); //System.exit(0); } } }
package com.atguigu.state; /** * 獎品發放完畢狀態 * 說明,當我們activity 改變成 DispenseOutState, 抽獎活動結束 * @author Administrator * */ public class DispenseOutState extends State { // 初始化時傳入活動引用 RaffleActivity activity; public DispenseOutState(RaffleActivity activity) { this.activity = activity; } @Override public void deductMoney() { System.out.println("獎品傳送完了,請下次再參加"); } @Override public boolean raffle() { System.out.println("獎品傳送完了,請下次再參加"); return false; } @Override public void dispensePrize() { System.out.println("獎品傳送完了,請下次再參加"); } }
package com.atguigu.state; import java.util.Random; /** * 可以抽獎的狀態 * @author Administrator * */ public class CanRaffleState extends State { RaffleActivity activity; public CanRaffleState(RaffleActivity activity) { this.activity = activity; } //已經扣除了積分,不能再扣 @Override public void deductMoney() { System.out.println("已經扣取過了積分"); } //可以抽獎, 抽完獎後,根據實際情況,改成新的狀態 @Override public boolean raffle() { System.out.println("正在抽獎,請稍等!"); Random r = new Random(); int num = r.nextInt(10); // 10%中獎機會 if(num == 0){ // 改變活動狀態為發放獎品 context activity.setState(activity.getDispenseState()); return true; }else{ System.out.println("很遺憾沒有抽中獎品!"); // 改變狀態為不能抽獎 activity.setState(activity.getNoRafflleState()); return false; } } // 不能發放獎品 @Override public void dispensePrize() { System.out.println("沒中獎,不能發放獎品"); } }
定義一個活動類:
package com.atguigu.state; /** * 抽獎活動 // * * @author Administrator * */ public class RaffleActivity { // state 表示活動當前的狀態,是變化 State state = null; // 獎品數量 int count = 0; // 四個屬性,表示四種狀態 State noRafflleState = new NoRaffleState(this); State canRaffleState = new CanRaffleState(this); State dispenseState = new DispenseState(this); State dispensOutState = new DispenseOutState(this); //構造器 //1. 初始化當前的狀態為 noRafflleState(即不能抽獎的狀態) //2. 初始化獎品的數量 public RaffleActivity( int count) { this.state = getNoRafflleState(); this.count = count; } //扣分, 呼叫當前狀態的 deductMoney public void debuctMoney(){ state.deductMoney(); } //抽獎 public void raffle(){ // 如果當前的狀態是抽獎成功 if(state.raffle()){ //領取獎品 state.dispensePrize(); } } public State getState() { return state; } public void setState(State state) { this.state = state; } //這裡請大家注意,每領取一次獎品,count-- public int getCount() { int curCount = count; count--; return curCount; } public void setCount(int count) { this.count = count; } public State getNoRafflleState() { return noRafflleState; } public void setNoRafflleState(State noRafflleState) { this.noRafflleState = noRafflleState; } public State getCanRaffleState() { return canRaffleState; } public void setCanRaffleState(State canRaffleState) { this.canRaffleState = canRaffleState; } public State getDispenseState() { return dispenseState; } public void setDispenseState(State dispenseState) { this.dispenseState = dispenseState; } public State getDispensOutState() { return dispensOutState; } public void setDispensOutState(State dispensOutState) { this.dispensOutState = dispensOutState; } }
然後進行測試:
package com.atguigu.state; /** * 狀態模式測試類 * @author Administrator * */ public class ClientTest { public static void main(String[] args) { // TODO Auto-generated method stub // 建立活動物件,獎品有1個獎品 RaffleActivity activity = new RaffleActivity(1); // 我們連續抽300次獎 for (int i = 0; i < 30; i++) { System.out.println("--------第" + (i + 1) + "次抽獎----------"); // 參加抽獎,第一步點選扣除積分 activity.debuctMoney(); // 第二步抽獎 activity.raffle(); } } }
優點:1、封裝了轉換規則。 2、列舉可能的狀態,在列舉狀態之前需要確定狀態種類。 3、將所有與某個狀態有關的行為放到一個類中,並且可以方便地增加新的狀態,只需要改變物件狀態即可改變物件的行為。 4、允許狀態轉換邏輯與狀態物件合成一體,而不是某一個巨大的條件語句塊。 5、可以讓多個環境物件共享一個狀態物件,從而減少系統中物件的個數。
缺點:1、狀態模式的使用必然會增加系統類和物件的個數。 2、狀態模式的結構與實現都較為複雜,如果使用不當將導致程式結構和程式碼的混亂。 3、狀態模式對"開閉原則"的支援並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的原始碼,否則無法切換到新增狀態,而且修改某個狀態類的行為也需修改對應類的原始碼。
使用場景:1、行為隨狀態改變而改變的場景。 2、條件、分支語句的代替者。
注意事項:在行為受狀態約束的時候使用狀態模式,而且狀態不超過 5 個。
10策略模式:使用介面分離把a,b,c三個方法,分成兩個介面分別有ab和bc
11職責鏈模式
完成這個專案,我們儘量少的使用esleif這樣才能增加程式碼的擴招性
於是我們就可以使用職責鏈模式:
首先擺出責任鏈:
package com.atguigu.responsibilitychain; public abstract class Approver { Approver approver; //下一個處理者 String name; // 名字 public Approver(String name) { // TODO Auto-generated constructor stub this.name = name; } //下一個處理者 public void setApprover(Approver approver) { this.approver = approver; } //處理審批請求的方法,得到一個請求, 處理是子類完成,因此該方法做成抽象 public abstract void processRequest(PurchaseRequest purchaseRequest); }
package com.atguigu.responsibilitychain; public class CollegeApprover extends Approver { public CollegeApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() > 5000 && purchaseRequest.getPrice() <= 10000) { System.out.println(" 請求編號 id= " + purchaseRequest.getId() + " 被 " + this.name + " 處理"); }else { approver.processRequest(purchaseRequest); } } }
package com.atguigu.responsibilitychain; public class DepartmentApprover extends Approver { public DepartmentApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() <= 5000) { System.out.println(" 請求編號 id= " + purchaseRequest.getId() + " 被 " + this.name + " 處理"); }else { approver.processRequest(purchaseRequest); } } }
package com.atguigu.responsibilitychain; public class SchoolMasterApprover extends Approver { public SchoolMasterApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() > 30000) { System.out.println(" 請求編號 id= " + purchaseRequest.getId() + " 被 " + this.name + " 處理"); }else { approver.processRequest(purchaseRequest); } } }
package com.atguigu.responsibilitychain; public class ViceSchoolMasterApprover extends Approver { public ViceSchoolMasterApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() > 10000 && purchaseRequest.getPrice() <= 30000) { System.out.println(" 請求編號 id= " + purchaseRequest.getId() + " 被 " + this.name + " 處理"); }else { approver.processRequest(purchaseRequest); } } }
再給出需求物件:
package com.atguigu.responsibilitychain; //請求類 public class PurchaseRequest { private int type = 0; //請求型別 private float price = 0.0f; //請求金額 private int id = 0; //構造器 public PurchaseRequest(int type, float price, int id) { this.type = type; this.price = price; this.id = id; } public int getType() { return type; } public float getPrice() { return price; } public int getId() { return id; } }
客戶端結果:
package com.atguigu.responsibilitychain; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //建立一個請求 PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1); //建立相關的審批人 DepartmentApprover departmentApprover = new DepartmentApprover("張主任"); CollegeApprover collegeApprover = new CollegeApprover("李院長"); ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校"); SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校長"); //需要將各個審批級別的下一個設定好 (處理人構成環形: ) departmentApprover.setApprover(collegeApprover); collegeApprover.setApprover(viceSchoolMasterApprover); viceSchoolMasterApprover.setApprover(schoolMasterApprover); schoolMasterApprover.setApprover(departmentApprover); departmentApprover.processRequest(purchaseRequest); viceSchoolMasterApprover.processRequest(purchaseRequest); } }
優點:1、降低耦合度。它將請求的傳送者和接收者解耦。 2、簡化了物件。使得物件不需要知道鏈的結構。 3、增強給物件指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。 4、增加新的請求處理類很方便。
缺點:1、不能保證請求一定被接收。 2、系統性能將受到一定影響,而且在進行程式碼除錯時不太方便,可能會造成迴圈呼叫。 3、可能不容易觀察執行時的特徵,有礙於除錯。
使用場景:1、有多個物件可以處理同一個請求,具體哪個物件處理該請求由執行時刻自動確定。 2、在不明確指定接收者的情況下,向多個物件中的一個提交一個請求。 3、可動態指定一組物件處理請求。
注意事項:在 JAVA WEB 中遇到很多應用。
在SpringMVC--攔截器中的使用: