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--拦截器中的使用: