Java设计模式(六):行为型模式(备忘录模式、解释器模式、状态模式、策略模式、职责链模式)

目录

一· 备忘录模式

1.1 游戏角色状态恢复问题

游戏角色有攻击力和防御力,在大战 Boss 前保存自身的状态(攻击力和防御力),当大战 Boss 后攻击力和防御 力下降,从备忘录对象恢复到大战前的状态 

1.2 传统方案解决游戏角色恢复

在这里插入图片描述

1.3 传统的方式的问题分析

1) 一个对象,就对应一个保存对象状态的对象, 这样当我们游戏的对象很多时,不利于管理,开销也很大. 
2) 传统的方式是简单地做备份,new 出另外一个对象出来,再把需要备份的数据放到这个新对象,但这就暴露了 
对象内部的细节 

3) 解决方案: => 备忘录模式 

1.4 备忘录模式基本介绍

基本介绍 

	1) 备忘录模式(Memento Pattern)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这 个状态。这样以后就可将该对象恢复到原先保存的状态
	2) 可以这里理解备忘录模式:现实生活中的备忘录是用来记录某些要去做的事情,或者是记录已经达成的共同意 见的事情,以防忘记了。而在软件层面,备忘录模式有着相同的含义,备忘录对象主要用来记录一个对象的某 种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作 
	3) 备忘录模式属于行为型模式 

1.5 备忘录模式的原理类图

在这里插入图片描述

对原理类图的说明-即(备忘录模式的角色及职责) 
	1) originator : 对象(需要保存状态的对象) 
	2) Memento : 备忘录对象,负责保存好记录,即 Originator 内部状态 
	3) Caretaker: 守护者对象,负责保存多个备忘录对象, 使用集合管理,提高效率 
	4) 说明:如果希望保存多个 originator 对象的不同时间的状态,也可以,只需要要 HashMap <String, 集合>

代码实现
package com.atzhu.memento.theory; 


import java.util.ArrayList; 
import java.util.List; 



public class Caretaker { 



	//在 List 集合中会有很多的备忘录对象 
	private List<Memento> mementoList = new ArrayList<Memento>(); 



	public void add(Memento memento) { 
		mementoList.add(memento); 
	}



	//获取到第 index 个 Originator 的 备忘录对象(即保存状态) 
	public Memento get(int index) { 
		return mementoList.get(index); 
	}
}



package com.atzhu.memento.theory; 



import java.util.ArrayList; 
import java.util.HashMap; 



public class Client { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		Originator originator = new Originator(); 
		Caretaker caretaker = new Caretaker(); 



		originator.setState(" 状态#1 攻击力 100 "); 



		//保存了当前的状态 
		caretaker.add(originator.saveStateMemento()); 



		originator.setState(" 状态#2 攻击力 80 "); 



		caretaker.add(originator.saveStateMemento()); 



		originator.setState(" 状态#3 攻击力 50 "); 
		caretaker.add(originator.saveStateMemento()); 
 

		System.out.println("当前的状态是 =" + originator.getState()); 



		//希望得到状态 1, 将 originator 恢复到状态 1 
		originator.getStateFromMemento(caretaker.get(0)); 
		System.out.println("恢复到状态 1 , 当前的状态是"); 
		System.out.println("当前的状态是 =" + originator.getState()); 

	}
}



package com.atzhu.memento.theory; 



public class Memento { 
	private String state; 



	//构造器 
	public Memento(String state) { 
		super(); 
		this.state = state; 
	}



	public String getState() { 
		return state; 
	}

}



package com.atzhu.memento.theory; 



public class Originator { 



	private String state;//状态信息 



	public String getState() { 
		return state; 
	}



	public void setState(String state) { 
		this.state = state; 
	}



	//编写一个方法,可以保存一个状态对象 Memento 
	//因此编写一个方法,返回 Memento 
	public Memento saveStateMemento() { 
		return new Memento(state); 
	}



	//通过备忘录对象,恢复状态 
	public void getStateFromMemento(Memento memento) { 
		state = memento.getState(); 
	}
}

1.6 游戏角色恢复状态实例

1) 应用实例要求 
	游戏角色有攻击力和防御力,在大战 Boss 前保存自身的状态(攻击力和防御力),当大战 Boss 后攻击力和防御 力下降,从备忘录对象恢复到大战前的状态 

2) 思路分析和图解(类图)

在这里插入图片描述

3)代码实现
package com.atzhu.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; 
	}

}



package com.atzhu.memento.game; 



public class Client { 



	public static void main(String[] args) { 


		// TODO Auto-generated method stub 
		//创建游戏角色 
		GameRole gameRole = new GameRole(); 
		gameRole.setVit(100); gameRole.setDef(100); 



		System.out.println("和 boss 大战前的状态"); 
		gameRole.display(); 



		//把当前状态保存 caretaker 
		Caretaker caretaker = new Caretaker(); 
		caretaker.setMemento(gameRole.createMemento()); 



		System.out.println("和 boss 大战~~~"); 
		gameRole.setDef(30); gameRole.setVit(30); 



		gameRole.display(); 



		System.out.println("大战后,使用备忘录对象恢复到站前"); 



		gameRole.recoverGameRoleFromMemento(caretaker.getMemento()); 
		System.out.println("恢复后的状态"); 
		gameRole.display(); 

 
	}
}



package com.atzhu.memento.game; 



public class GameRole { 



	private int vit; 
	private int def; 



	//创建 Memento ,即根据当前的状态得到 Memento 
	public Memento createMemento() { 
		return new Memento(vit, def); 
	}



	//从备忘录对象,恢复 GameRole 的状态 
	public void recoverGameRoleFromMemento(Memento memento) { 
		this.vit = memento.getVit(); 
		this.def = memento.getDef(); 
	}



	//显示当前游戏角色的状态 
	public void display() { 
		System.out.println("游戏角色当前的攻击力:" + this.vit + " 防御力: " + this.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.atzhu.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; 
	}

}

1.7 备忘录模式的注意事项和细节

1) 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态 
2) 实现了信息的封装,使得用户不需要关心状态的保存细节 
3) 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存, 这个需要注意 
4) 适用的应用场景:1、后悔药。 2、打游戏时的存档。 3、Windows 里的 ctri + z。 4、IE 中的后退。 4、数据库的事务管理 
5) 为了节约内存,备忘录模式可以和原型模式配合使用

二· 解释器模式

2.1 四则运算问题

通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 
	1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 
	2) 在分别输入 a ,b, c, d, e 的值 
	3) 最后求出结果:如图

在这里插入图片描述

2.2 传统方案解决四则运算问题分析

1) 编写一个方法,接收表达式的形式,然后根据用户输入的数值进行解析,得到结果 
2) 问题分析:如果加入新的运算符,比如 * / ( 等等,不利于扩展,另外让一个方法来解析会造成程序结构混乱, 不够清晰. 
3) 解决方案:可以考虑使用解释器模式, 即: 表达式 -> 	解释器(可以有多种) 	-> 	结果 

2.3 解释器模式基本介绍

基本介绍 

	1) 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法 分析树,最终形成一颗抽象的语法分析树。
		这里的词法分析器和语法分析器都可以看做是解释器 
	2) 解释器模式(Interpreter Pattern):是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器, 使用该解释器来解释语言中的句子(表达式) 
	3) 应用场景 
		-应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树 
		-一些重复出现的问题可以用一种简单的语言来表达 
		-一个简单语法需要解释的场景 
	4) 这样的例子还有,比如编译器、运算表达式计算、正则表达式、机器人等 

2.4 解释器模式的原理类图

在这里插入图片描述

对原理类图的说明-即(解释器模式的角色及职责) 
	1) Context: 是环境角色,含有解释器之外的全局信息. 
	2) AbstractExpression: 抽象表达式, 声明一个抽象的解释操作,这个方法为抽象语法树中所有的节点所共享 
	3) TerminalExpression: 为终结符表达式, 实现与文法中的终结符相关的解释操作 
	4) NonTermialExpression: 为非终结符表达式,为文法中的非终结符实现解释操作. 
	5) 说明: 输入 Context he TerminalExpression 信息通过 Client 输入即可 

2.5 解释器模式来实现四则

1) 应用实例要求 
	通过解释器模式来实现四则运算, 
	如计算 a+b-c 的值 

2) 思路分析和图解(类图)

在这里插入图片描述

3)代码实现
package com.atzhu.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.atzhu.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" 
				stack 
 
				right = new VarExpression(String.valueOf(charArray[++i]));// 取出右表达式 "b" 
				stack.push(new AddExpression(left, right));// 然后根据得到 left 和 right 构建 AddExpresson 加入 



				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.atzhu.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.atzhu.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.atzhu.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.atzhu.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.atzhu.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); 
	}
}

2.6 解释器模式在 Spring 框架应用的源码剖析

1) Spring 框架中 SpelExpressionParser 就使用到解释器模式 
2) 代码分析+Debug 源码

在这里插入图片描述

3)说明

在这里插入图片描述

2.7 解释器模式的注意事项和细节

1) 当有一个语言需要解释执行,可将该语言中的句子表示为一个抽象语法树,就可以考虑使用解释器模式,让程 序具有良好的扩展性 
2) 应用场景:编译器、运算表达式计算、正则表达式、机器人等 
3) 使用解释器可能带来的问题:解释器模式会引起类膨胀、解释器模式采用递归调用方法,将会导致调试非常复 杂、效率可能降低.

三· 状态模式

3.1 APP 抽奖活动问题

请编写程序完成 APP 抽奖活动 具体要求如下: 
	1) 假如每参加一次这个活动要扣除用户 50 积分,中奖概率是 10% 
	2) 奖品数量固定,抽完就不能抽奖 
	3) 活动有四个状态: 可以抽奖、不能抽奖、发放奖品和奖品领完 
	4) 活动的四个状态转换关系图(右图)

在这里插入图片描述

3.2 状态模式基本介绍

基本介绍 

	1) 状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态 和行为是一一对应的,状态之间可以相互转换 
	2) 当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类 

3.3 状态模式的原理类图

在这里插入图片描述

对原理类图的说明-即(状态模式的角色及职责) 
	1) Context 类为环境角色, 用于维护 State 实例,这个实例定义当前状态 
	2) State 是抽象状态角色,定义一个接口封装与 Context 的一个特点接口相关行为 
	3) ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为 

3.4 状态模式解决 APP 抽奖问

1) 应用实例要求 
	完成 APP 抽奖活动项目,使用状态模式. 
2) 思路分析和图解(类图) 
	-定义出一个接口叫状态接口,每个状态都实现它。 
	-接口有扣除积分方法、抽奖方法、发放奖品方法

在这里插入图片描述

3)代码实现
package com.atzhu.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.atzhu.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(); 
		}
	}
}



package com.atzhu.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.atzhu.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.atzhu.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.atzhu.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.atzhu.state; 



/ ** 
* 状态抽象类 
* @author Administrator 
*
*/ 
public abstract class State { 





	// 扣除积分 - 50 
	public abstract void deductMoney(); 



	// 是否抽中奖品 
	public abstract boolean raffle(); 



	// 发放奖品 
	public abstract void dispensePrize(); 
}

3.5 状态模式在实际项目-借贷平台 源码剖析

1) 借贷平台的订单,有审核-发布-抢单 等等 步骤,随着操作的不同,会改变订单的状态, 项目中的这个模块实 现就会使用到状态模式 

2) 通常通过 if/else 判断订单的状态,从而实现不同的逻辑,伪代码如下

在这里插入图片描述

3) 使用状态模式完成 借贷平台项目的审核模块 [设计+代码]
package com.atzhu.state.money; 



public abstract class AbstractState implements State { 



	protected static final RuntimeException EXCEPTION = new RuntimeException("操作流程不允许"); 



	//抽象类,默认实现了 State 接口的所有方法 
	//该类的所有方法,其子类(具体的状态类),可以有选择的进行重写 
	@Override 
	public void checkEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void checkFailEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void makePriceEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void acceptOrderEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void notPeopleAcceptEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void payOrderEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void orderFailureEvent(Context context) { 
		throw EXCEPTION; 
	}



	@Override 
	public void feedBackEvent(Context context) { 
		throw EXCEPTION; 
	}

}



package com.atzhu.state.money; 



//各种具体状态类 
class FeedBackState extends AbstractState { 



	@Override 
	public String getCurrentState() { 
		return StateEnum.FEED_BACKED.getValue(); 
	}
}

class GenerateState extends AbstractState { 



	@Override 
	public void checkEvent(Context context) { 
		context.setState(new ReviewState()); 
	}



	@Override 
	public void checkFailEvent(Context context) { 
		context.setState(new FeedBackState()); 
	}



	@Override 
	public String getCurrentState() { 
		return StateEnum.GENERATE.getValue(); 
	}
}



class NotPayState extends AbstractState { 



	@Override 
	public void payOrderEvent(Context context) { 
		context.setState(new PaidState()); 
	}



	@Override 
	public void feedBackEvent(Context context) { 
		context.setState(new FeedBackState()); 
	}



	@Override 
	public String getCurrentState() { 
		return StateEnum.NOT_PAY.getValue(); 
	}
}



class PaidState extends AbstractState { 



	@Override 
	public void feedBackEvent(Context context) { 
		context.setState(new FeedBackState()); 
	}



	@Override 
	public String getCurrentState() { 
		return StateEnum.PAID.getValue(); 
	}
}



class PublishState extends AbstractState { 



	@Override 
	public void acceptOrderEvent(Context context) { 
		//把当前状态设置为 	NotPayState。。。 
		//至于应该变成哪个状态,有流程图来决定 
		context.setState(new NotPayState()); 
	}



	@Override 
	public void notPeopleAcceptEvent(Context context) { 
		context.setState(new FeedBackState()); 
	}



	@Override 
	public String getCurrentState() { 
		return StateEnum.PUBLISHED.getValue(); 
	}
 
}



class ReviewState extends AbstractState { 



	@Override 
	public void makePriceEvent(Context context) { 
		context.setState(new PublishState()); 
	}



	@Override 
	public String getCurrentState() { 
		return StateEnum.REVIEWED.getValue(); 
	}
}


package com.atzhu.state.money; 



/**测试类*/ 
public class ClientTest { 



	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//创建 context 对象 
		Context context = new Context(); 
		//将当前状态设置为 PublishState 
		context.setState(new PublishState()); 
		System.out.println(context.getCurrentState()); 
 
// 


// 

// 
// // // // 
		//publish --> not pay 
		context.acceptOrderEvent(context); 
		//not pay --> paid 
		context.payOrderEvent(context); 
		// 失败, 检测失败时,会抛出异常 
		try { 
			context.checkFailEvent(context); System.out.println("流程正常.."); 
		} catch (Exception e) { 
 
			// TODO: handle exception 
			System.out.println(e.getMessage()); 
		}
	}
}
 



package com.atguigu.state.money; 



//环境上下文 
public class Context extends AbstractState{ 
	//当前的状态 state, 根据我们的业务流程处理,不停的变化 
	private State state; 



	@Override 
	public void checkEvent(Context context) { 
		state.checkEvent(this); 
		getCurrentState(); 
	}



	@Override 
	public void checkFailEvent(Context context) { 
		state.checkFailEvent(this); 
		getCurrentState(); 
	}

	@Override 
	public void makePriceEvent(Context context) { 
		state.makePriceEvent(this); 
		getCurrentState(); 
	}



	@Override 
	public void acceptOrderEvent(Context context) { 
		state.acceptOrderEvent(this); 
		getCurrentState(); 
	}



	@Override 
	public void notPeopleAcceptEvent(Context context) { 
		state.notPeopleAcceptEvent(this); 
		getCurrentState(); 
	}



	@Override 
	public void payOrderEvent(Context context) { 
		state.payOrderEvent(this); 
		getCurrentState(); 
	}



	@Override 
	public void orderFailureEvent(Context context) { 
		state.orderFailureEvent(this); 
		getCurrentState(); 
	}



	@Override 
	public void feedBackEvent(Context context) { 
		state.feedBackEvent(this); 
		getCurrentState(); 
	}



	public State getState() { 
		return state; 
	}



	public void setState(State state) { 
		this.state = state; 
	}



	@Override 
	public String getCurrentState() { 
		System.out.println("当前状态 : " + state.getCurrentState()); 
		return state.getCurrentState(); 
	} 
}




package com.atzhu.state.money; 



/ ** 
* 状态接口 
* @author Administrator 
*
*/ 
public interface State { 



	/ ** 
	* 电审 
	*/ 
	void checkEvent(Context context); 



	/ ** 
	* 电审失败 
	*/ 
	void checkFailEvent(Context context); 



	/ ** 
	* 定价发布 
	*/ 
	void makePriceEvent(Context context); 



	/ ** 
	* 接单 
	*/ 
	void acceptOrderEvent(Context context); 



	/ ** 
	* 无人接单失效 
	*/ 
	void notPeopleAcceptEvent(Context context); 



	/ ** 
	* 付款 
	*/ 
	void payOrderEvent(Context context); 



	/ ** 
	* 接单有人支付失效 
	*/ 
	void orderFailureEvent(Context context); 



	/ ** 
	* 反馈 
	*/ 
	void feedBackEvent(Context context); 
 
	String getCurrentState(); 
}



package com.atzhu.state.money; 



/ ** 
* 状态枚举类 
* @author Administrator 
*
*/ 
public enum StateEnum { 



	//订单生成 
	GENERATE(1, "GENERATE"), 



	//已审核 
	REVIEWED(2, "REVIEWED"), 



	//已发布 
	PUBLISHED(3, "PUBLISHED"), 



	//待付款 
	NOT_PAY(4, "NOT_PAY"), 



	//已付款 
	PAID(5, "PAID"), 



	//已完结 
	FEED_BACKED(6, "FEED_BACKED"); 



	private int key; 
	private String value; 



	StateEnum(int key, String value) { 
		this.key = key; 
		this.value = value; 
	}
	public int getKey() {return key;} 
	public String getValue() {return value;} 
  
}

3.6 状态模式的注意事项和细节

1) 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中 
2) 方便维护。将容易产生问题的 if-else 语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都 要判断当前是什么状态,不但会产出很多 if-else 语句,而且容易出错 
3) 符合"开闭原则"。容易增删状态 
4) 会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度 
5) 应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式 

四· 策略模式

4.1 编写鸭子项目,具体要求如下:

1) 有各种鸭子(比如 野鸭、北京鸭、水鸭等, 鸭子有各种行为,比如 叫、飞行等) 
2) 显示鸭子的信息 

4.2 传统方案解决鸭子问题的分析和代码实现

1) 传统的设计方案(类图)

在这里插入图片描述

2) 代码实现-看老师演示
package com.atzhu.strategy; 



public class Client { 


	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		//测试 
	}

}



package com.atzhu.strategy; 



public abstract class Duck { 



	public Duck() { 

	}



	public abstract void display();//显示鸭子信息 



	public void quack() { 
		System.out.println("鸭子嘎嘎叫~~"); 
	}



	public void swim() { 
		System.out.println("鸭子会游泳~~"); 
	}



	public void fly() { 
		System.out.println("鸭子会飞翔~~~"); 
	}
}



package com.atzhu.strategy; 

public class PekingDuck extends Duck { 



	@Override 
	public void display() { 
		// TODO Auto-generated method stub 	
		System.out.println("~~北京鸭~~~"); 
	}



	//因为北京鸭不能飞翔,因此需要重写 fly 
	@Override 
	public void fly() { 
		// TODO Auto-generated method stub 
		System.out.println("北京鸭不能飞翔"); 
	}
}



package com.atzhu.strategy; 



public class ToyDuck extends Duck{ 



	@Override 
	public void display() { 
		// TODO Auto-generated method stub 
		System.out.println("玩具鸭"); 
	}



	//需要重写父类的所有方法 
	public void quack() { 
		System.out.println("玩具鸭不能叫~~"); 
	}



	public void swim() { 
		System.out.println("玩具鸭不会游泳~~"); 
	}



	public void fly() { 
		System.out.println("玩具鸭不会飞翔~~~"); 
	}
}



package com.atzhu.strategy; 



public class WildDuck extends Duck { 



	@Override 
	public void display() { 
		// TODO Auto-generated method stub 
		System.out.println(" 这是野鸭 "); 
	}
}

4.3 传统的方式实现的问题分析和解决方案

1) 其它鸭子,都继承了 Duck 类,所以 fly 让所有子类都会飞了,这是不正确的 
2) 上面说的 1 的问题,其实是继承带来的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。会有 溢出效应 
3) 为了改进 1 问题,我们可以通过覆盖 fly 方法来解决 => 覆盖解决 
4) 问题又来了,如果我们有一个玩具鸭子 ToyDuck, 这样就需要 ToyDuck 去覆盖 Duck 的所有实现的方法 => 解 决思路 -》 策略模式 (strategy pattern) 

4.4 策略模式基本介绍

1) 策略模式(Strategy Pattern)中,定义算法族(策略组),分别封装起来,让他们之间可以互相替换,此模式 让算法的变化独立于使用算法的客户 
2) 这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体 类(定义了策略接口);第三、多用组合/聚合,少用继承(客户通过组合方式使用策略)。 

4.5 策略模式的原理类图

在这里插入图片描述

	说明:从上图可以看到,客户 context 有成员变量 strategy 或者其他的策略接口 
	,至于需要使用到哪个策略,我们可以在构造器中指定 

4.6 策略模式解决鸭子问题

1) 应用实例要求 
	编写程序完成前面的鸭子项目,要求使用策略模式 
2) 思路分析(类图) 
	策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。
	原则就是: 分离变化部分,封装接口,基于接口编程各种功能。此模式让行为的变化独立于算法的使用者

在这里插入图片描述

3)代码实现
package com.atzhu.strategy.improve; 



public class BadFlyBehavior implements FlyBehavior { 

	@Override 
	public void fly() { 
		// TODO Auto-generated method stub 
		System.out.println(" 飞翔技术一般 "); 
	}

}



package com.atzhu.strategy.improve; 



public class Client { 



	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		WildDuck wildDuck = new WildDuck(); 
		wildDuck.fly();// 



		ToyDuck toyDuck = new ToyDuck(); 
		toyDuck.fly(); 



		PekingDuck pekingDuck = new PekingDuck(); 
		pekingDuck.fly(); 



		//动态改变某个对象的行为, 北京鸭 不能飞 
		pekingDuck.setFlyBehavior(new NoFlyBehavior()); 
		System.out.println("北京鸭的实际飞翔能力"); 
		pekingDuck.fly(); 
	}
}
 



package com.atzhu.strategy.improve; 



public abstract class Duck { 



	//属性, 策略接口 
	FlyBehavior flyBehavior; //其它属性<->策略接口 
	QuackBehavior quackBehavior; 



	public Duck() { 



	}



	public abstract void display();//显示鸭子信息 



	public void quack() { 
		System.out.println("鸭子嘎嘎叫~~"); 
	}



	public void swim() { 
		System.out.println("鸭子会游泳~~"); 
	}



	public void fly() { 



		//改进 
		if(flyBehavior != null) { 
			flyBehavior.fly(); 
		}
	}



	public void setFlyBehavior(FlyBehavior flyBehavior) { 
		this.flyBehavior = flyBehavior; 
	}





	public void setQuackBehavior(QuackBehavior quackBehavior) { 
		this.quackBehavior = quackBehavior; 
	}

}



package com.atzhu.strategy.improve; 



public interface FlyBehavior { 

		void fly(); // 子类具体实现 
}



package com.atzhu.strategy.improve; 



public class GoodFlyBehavior implements FlyBehavior { 



	@Override 
	public void fly() { 
		// TODO Auto-generated method stub 
		System.out.println(" 飞翔技术高超 ~~~"); 
	}
}



package com.atzhu.strategy.improve; 



public class NoFlyBehavior implements FlyBehavior{ 



	@Override 
	public void fly() { 
		// TODO Auto-generated method stub 
		System.out.println(" 不会飞翔 "); 
	}

}



package com.atzhu.strategy.improve; 



public class PekingDuck extends Duck { 





	//假如北京鸭可以飞翔,但是飞翔技术一般 
	public PekingDuck() { 
		// TODO Auto-generated constructor stub 
		flyBehavior = new BadFlyBehavior();
	}



	@Override 
	public void display() { 
		// TODO Auto-generated method stub 		
		System.out.println("~~北京鸭~~~"); 
	}
}



package com.atzhu.strategy.improve; 



public interface QuackBehavior { 
	void quack();//子类实现 
}



package com.atzhu.strategy.improve; 



public class ToyDuck extends Duck{ 
 
	public ToyDuck() { 
		// TODO Auto-generated constructor stub 
		flyBehavior = new NoFlyBehavior(); 
	}



	@Override 
	public void display() { 
		// TODO Auto-generated method stub 
		System.out.println("玩具鸭"); 
	}



	//需要重写父类的所有方法 
	public void quack() { 
		System.out.println("玩具鸭不能叫~~"); 
	}

	public void swim() { 
		System.out.println("玩具鸭不会游泳~~"); 
	}

}



package com.atzhu.strategy.improve; 



public class WildDuck extends Duck { 



	//构造器,传入 FlyBehavor 的对象 
	public WildDuck() { 
		// TODO Auto-generated constructor stub 
		flyBehavior = new GoodFlyBehavior(); 
	}



	@Override 
	public void display() { 
		// TODO Auto-generated method stub 
		System.out.println(" 这是野鸭 "); 
	}

}

4.7 策略模式在 JDK-Arrays 应用的源码分析

1) JDK 的 Arrays 的 Comparator 就使用了策略模式 
2) 代码分析+Debug 源码+模式角色分析

在这里插入图片描述

		代码
package com.atzhu.jdk; 



import java.util.Arrays; 
import java.util.Comparator; 





public class Strategy { 



	public static void main(String[] args) { 



		// TODO Auto-generated method stub 
		//数组 
		Integer[] data = { 9, 1, 2, 8, 4, 3 }; 
		// 实现降序排序,返回-1 放左边,1 放右边,0 保持不变 
		// 说明 
		// 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..} 
		// 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象 
		// 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式 
		Comparator<Integer> comparator = new Comparator<Integer>() { 
			public int compare(Integer o1, Integer 			o2) { 
			if (o1 > o2) { 
				return -1; 
			} else { 
				return 1; 
			}
		}; 
	}; 



	// 说明 
	/* 
	* public static <T> void sort(T[] a, Comparator<? super T> c) { 
		if (c == null) { 
			sort(a); //默认方法 
		} else { 
			if (LegacyMergeSort.userRequested) 
	legacyMergeSort(a, c); //使用策略对象 c 
	else 
		// 使用策略对象 c 
		TimSort.sort(a, 0, a.length, c, null, 0, 0); 
		}
	}
	*/ 
	//方式 1 
	Arrays.sort(data, comparator); 



	System.out.println(Arrays.toString(data)); // 降序排序 


	//方式 2- 同时 lambda 表达式实现 策略模式 
	Integer[] data2 = { 19, 11, 12, 18, 14, 13 }; 



	Arrays.sort(data2, (var1, var2) -> { 
		if(var1.compareTo(var2) > 0) { 
			return -1; 
		} else { 
			return 1; 
		}
	}); 


	System.out.println("data2=" + Arrays.toString(data2)); 

	}

}

4.8 策略模式的注意事项和细节

1) 策略模式的关键是:分析项目中变化部分与不变部分 
2) 策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性 
3) 体现了"对修改关闭,对扩展开放"原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可,避免了使用多重转移语句(if..else if..else) 
4) 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改 变它,使它易于切换、易于理解、易于扩展 

5) 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞

五· 职责链模式

5.1 学校 OA 系统的采购审批项目:需求是

采购员采购教学器材 

	1) 如果金额 小于等于 5000, 由教学主任审批 (0<=x<=5000) 
	2) 如果金额 小于等于 10000, 由院长审批 (5000<x<=10000) 
	3) 如果金额 小于等于 30000, 由副校长审批 (10000<x<=30000) 
	4) 如果金额 超过 30000 以上,有校长审批 ( 30000<x) 请设计程序完成采购审批项目 

5.2 传统方案解决 OA 系统审批,传统的设计方案(类图)

在这里插入图片描述

5.3 传统方案解决 OA 系统审批问题分析

1) 传统方式是:接收到一个采购请求后,根据采购金额来调用对应的 Approver (审批人)完成审批。 
2) 传统方式的问题分析 : 	客户端这里会使用到 分支判断(比如 switch) 来对不同的采购请求处理, 这样就存在 
	如下问题 (1) 如果各个级别的人员审批金额发生变化,在客户端的也需要变化 (2) 客户端必须明确的知道 有 多少个审批级别和访问 
3) 这样 对一个采购请求进行处理 和 Approver (审批人) 就存在强耦合关系,不利于代码的扩展和维护 
4) 解决方案 =》 职责链模式 

5.4 职责链模式基本介绍

基本介绍 

1) 职责链模式(Chain of Responsibility Pattern), 又叫 责任链模式,为请求创建了一个接收者对象的链(简单示意 图)。这种模式对请求的发送者和接收者进行解耦。 
2) 职责链模式通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的 请求传给下一个接收者,依此类推。 
3) 这种类型的设计模式属于行为型模式 

5.5 职责链模式的原理类图

在这里插入图片描述

	对原理类图的说明-即(职责链模式的角色及职责) 
1) Handler : 抽象的处理者, 定义了一个处理请求的接口, 同时含义另外 Handler 
2) ConcreteHandlerA , B 是具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者), 如果 可以处理当前请求,则处理,否则就将该请求交个 后继者去处理,从而形成一个职责链 
3) Request , 含义很多属性,表示一个请求 

5.6 职责链模式解决 OA 系统采购审批

1) 应用实例要求 
	编写程序完成学校 OA 系统的采购审批项目:需求 
	采购员采购教学器材 

	如果金额 小于等于 5000, 由教学主任审批 
	如果金额 小于等于 10000, 由院长审批 
	如果金额 小于等于 30000, 由副校长审批 如果金额 超过 30000 以上,有校长审批 
2) 思路分析和图解(类图)

在这里插入图片描述

代码实现
package com.atzhu.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.atzhu.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); 
	}

}



package com.atzhu.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.atzhu.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.atzhu.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.atzhu.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.atzhu.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); 
		}
	}
}

5.7 职责链模式在 SpringMVC 框架应用的源码分析

1) SpringMVC-HandlerExecutionChain 类就使用到职责链模式 
2) SpringMVC 请求流程简图 
3) 代码分析+Debug 源码+说明 

在这里插入图片描述

	源码说明
package com.atzhu.spring.test; 



import org.springframework.web.servlet.HandlerExecutionChain; 
import org.springframework.web.servlet.HandlerInterceptor; 



public class ResponsibilityChain { 

	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		// DispatcherServlet 
//说明 
/* 
*
*	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 
*	HandlerExecutionChain mappedHandler = null; 
*	mappedHandler = getHandler(processedRequest);//获取到 HandlerExecutionChain 对象 
*	//在 mappedHandler.applyPreHandle 内部 得到啦 HandlerInterceptor interceptor 
*	//调用了拦截器的 interceptor.preHandle 
*	if (!mappedHandler.applyPreHandle(processedRequest, response)) { 
return; 
}



//说明:mappedHandler.applyPostHandle 方法内部获取到拦截器,并调用 
//拦截器的 	interceptor.postHandle(request, response, this.handler, mv); 
mappedHandler.applyPostHandle(processedRequest, response, mv); 
*	}
*
*
*	//说明:在 	mappedHandler.applyPreHandle 内部中, 
*	还调用了 	triggerAfterCompletion 方法,该方法中调用了 
*/ 

		HandlerInterceptor interceptor = getInterceptors()[i]; 
		try { 
			interceptor.afterCompletion(request, response, this.handler, ex); 
		}catch (Throwable ex2) { 
			logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); 
		}
 

	}

}
5) 对源码总结 

	springmvc 请求的流程图中,执行了 拦截器相关方法 interceptor.preHandler 等等 
	在处理 SpringMvc 请求时,使用到职责链模式还使用到适配器模式 
	HandlerExecutionChain 主要负责的是请求拦截器的执行和请求处理,但是他本身不处理请求,只是将请求分配 给链上注册处理器执行,这是职责链实现方式,减少职责链本身与处理逻辑之间的耦合,规范了处理流程 
	HandlerExecutionChain 维护了 HandlerInterceptor 的集合, 可以向其中注册相应的拦截器. 

5.8 职责链模式的注意事项和细节

1) 将请求和处理分开,实现解耦,提高系统的灵活性 
2) 简化了对象,使对象不需要知道链的结构 
3) 性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个 最大节点数量,在 setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地 破坏系统性能 式 
4) 调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂 对 Encoding 的处理、拦截器 
5) 最佳应用场景: 多个对象可以处理同一个请求时, 如: 级请求、 假/加薪等审批流程、ava Web 中 Tomcat 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱yoyo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值