您的位置:首页 > 其它

状态模式(State)

2016-07-23 12:39 351 查看

1. 模式的定义

考虑一个在线投票的应用。

状态模式的定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

2. UML图



Context:上下文,通常用来定义客户感兴趣的接口,同时维护一个来具体处理当前状态的实例对象

State:状态接口,用来封装与上下文的一个特定状态所对应的行为

ConcreteState:具体实现状态处理的类,每个类实现一个跟上下文相关的状态的具体处理

代码:

/**
* 封装一个投票状态相关的行为
*/
public interface VoteState {
/**
* 处理状态对应的行为
* @param user 投票人
* @param voteItem 投票项
* @param voteManager 投票上下文,用来在实现状态对应的功能处理的时候,
*                    可以回调上下文的数据
*/
public void vote(String user,String voteItem,VoteManager voteManager);
}

public class NormalVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//正常投票
//记录到投票记录中
voteManager.getMapVote().put(user, voteItem);
System.out.println("恭喜你投票成功");
}
}

public class RepeatVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//重复投票
//暂时不做处理
System.out.println("请不要重复投票");
}
}

public class SpiteVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//恶意投票
//取消用户的投票资格,并取消投票记录
String s = voteManager.getMapVote().get(user);
if(s!=null){
voteManager.getMapVote().remove(user);
}
System.out.println("你有恶意刷票行为,取消投票资格");
}
}

public class BlackVoteState implements VoteState{
public void vote(String user, String voteItem, VoteManager voteManager) {
//黑名单
//记入黑名单中,禁止登录系统了
System.out.println("进入黑名单,将禁止登录和使用本系统");
}
}

/**
* 投票管理
*/
public class VoteManager {
/**
* 持有状态处理对象
*/
private VoteState state = null;
/**
* 记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项>
*/
private Map<String,String> mapVote = new HashMap<String,String>();
/**
* 记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>
*/
private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>();

/**
* 获取记录用户投票结果的Map
* @return 记录用户投票结果的Map
*/
public Map<String, String> getMapVote() {
return mapVote;
}

/**
* 投票
* @param user 投票人,为了简单,就是用户名称
* @param voteItem 投票的选项
*/
public void vote(String user,String voteItem){
//1:先为该用户增加投票的次数
//先从记录中取出已有的投票次数
Integer oldVoteCount = mapVoteCount.get(user);
if(oldVoteCount==null){
oldVoteCount = 0;
}
oldVoteCount = oldVoteCount + 1;
mapVoteCount.put(user, oldVoteCount);

//2:判断该用户投票的类型,就相当于是判断对应的状态
//到底是正常投票、重复投票、恶意投票还是上黑名单的状态
if(oldVoteCount==1){
state = new NormalVoteState();
}else if(oldVoteCount>1 && oldVoteCount<5){
state = new RepeatVoteState();
}else if(oldVoteCount >= 5 && oldVoteCount<8){
state = new SpiteVoteState();
}else if(oldVoteCount>=8){
state = new BlackVoteState();
}
//然后转调状态对象来进行相应的操作
state.vote(user, voteItem, this);
}
}

public class Client {
public static void main(String[] args) {
VoteManager vm = new VoteManager();
for(int i=0;i<8;i++){
vm.vote("u1", "A");
}
}
}


3. 研磨设计模式

1)不同的状态对应的状态处理(行为)是不相同的

2)状态模式的行为是平行性的(层次一样,相互独立,没有关联),不可相互替换,而策略模式的行为是平等性的,是可以相互替换的

3)状态模式的本质:根据状态来分离和选择行为

4)工作流

请假的工作流:

/**
* 公共状态处理机,相当于状态模式的Context
* 包含所有流程使用状态模式时的公共功能
*/
public  class StateMachine {
/**
* 持有一个状态对象
*/
private State state = null;
/**
* 包含流程处理需要的业务数据对象,不知道具体类型,
* 用Object,反正只是传递到具体的状态对象里面
*/
private Object businessVO = null;
/**
* 执行工作,客户端处理流程的接口方法。
* 在客户完成自己的业务工作后调用
*/
public void doWork(){
//转调相应的状态对象真正完成功能处理
this.state.doWork(this);
}

public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public Object getBusinessVO() {
return businessVO;
}
public void setBusinessVO(Object businessVO) {
this.businessVO = businessVO;
}
}

/**
* 公共状态接口
*/
public interface State {
/**
* 执行状态对应的功能处理
* @param ctx 上下文的实例对象
*/
public void doWork(StateMachine ctx);
}

/**
* 请假单对象
*/
public class LeaveRequestModel {
/**
* 请假人
*/
private String user;
/**
* 请假开始时间
*/
private String beginDate;
/**
* 请假天数
*/
private int leaveDays;
/**
* 审核结果
*/
private String result;

public String getResult() {
return result;
}

public void setResult(String result) {
this.result = result;
}

public String getUser() {
return user;
}

public String getBeginDate() {
return beginDate;
}

public int getLeaveDays() {
return leaveDays;
}
public void setUser(String user) {
this.user = user;
}

public void setBeginDate(String beginDate) {
this.beginDate = beginDate;
}

public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
}

public class LeaveRequestContext extends StateMachine{
//这里可以扩展跟自己流程相关的处理
}

public interface LeaveRequestState extends State{
//这里可以扩展跟自己流程相关的处理
}

/**
* 处理项目经理的审核,处理后可能对应部门经理审核、审核结束之中的一种
*/
public class ProjectManagerState implements LeaveRequestState{
public void doWork(StateMachine request) {
//先把业务对象造型回来
LeaveRequestModel lrm = (LeaveRequestModel)request.getBusinessVO();

System.out.println("项目经理审核中,请稍候......");

//模拟用户处理界面,通过控制台来读取数据
System.out.println(lrm.getUser()+"申请从"+lrm.getBeginDate()+
"开始请假"+lrm.getLeaveDays()+"天,请项目经理审核(1为同意,2为不同意):");
//读取从控制台输入的数据
Scanner scanner = new Scanner(System.in);
if(scanner.hasNext()){
int a = scanner.nextInt();
//设置回到上下文中
String result = "不同意";
if(a==1){
result = "同意";
}
lrm.setResult("项目经理审核结果:"+result);
//根据选择的结果和条件来设置下一步
if(a==1){
if(lrm.getLeaveDays() > 3){
//如果请假天数大于3天,而且项目经理同意了,就提交给部门经理
request.setState(new DepManagerState());
//继续执行下一步工作
request.doWork();
}else{
//3天以内的请假,由项目经理做主,就不用提交给部门经理了,转向审核结束状态
request.setState(new  AuditOverState());
//继续执行下一步工作
request.doWork();
}
}else{
//项目经理要是不同意的话,也就不用提交给部门经理了,转向审核结束状态
request.setState(new  AuditOverState());
//继续执行下一步工作
request.doWork();
}
}
}
}

/**
* 处理部门经理的审核,处理后对应审核结束状态
*/
public class DepManagerState implements LeaveRequestState{
public void doWork(StateMachine request) {
//先把业务对象造型回来
LeaveRequestModel lrm = (LeaveRequestModel)request.getBusinessVO();
System.out.println("部门经理审核中,请稍候......");

//模拟用户处理界面,通过控制台来读取数据
System.out.println(lrm.getUser()+"申请从"+lrm.getBeginDate()+
"开始请假"+lrm.getLeaveDays()+"天,请部门经理审核(1为同意,2为不同意):");
//读取从控制台输入的数据
Scanner scanner = new Scanner(System.in);
if(scanner.hasNext()){
int a = scanner.nextInt();
//设置回到上下文中
String result = "不同意";
if(a==1){
result = "同意";
}
lrm.setResult("部门经理审核结果:"+result);
//部门经理审核过后,直接转向审核结束状态了
request.setState(new AuditOverState());
//继续执行下一步工作
request.doWork();
}
}
}

/**
* 处理审核结束的类
*/
public class AuditOverState implements LeaveRequestState{
public void doWork(StateMachine request) {
//先把业务对象造型回来
LeaveRequestModel lrm = (LeaveRequestModel)request.getBusinessVO();
System.out.println(lrm.getUser()+",你的请假申请已经审核结束,结果是:"+lrm.getResult());
}
}

public class Client {
public static void main(String[] args) {
//创建业务对象,并设置业务数据
LeaveRequestModel lrm = new LeaveRequestModel();
lrm.setUser("小李");
lrm.setBeginDate("2010-02-08");
lrm.setLeaveDays(5);

//创建上下文对象
LeaveRequestContext request = new LeaveRequestContext();
//为上下文对象设置业务数据对象
request.setBusinessVO(lrm);
//配置上下文,作为开始的状态,以后就不管了
request.setState(new ProjectManagerState());

//请求上下文,让上下文开始处理工作
request.doWork();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: