1,状态模式的定义
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了他的类. |
2,uml图 顺序图
- Context:环境,也称上下文,通常用来定义客户感兴趣的接口,同时维护一个来具体处理当前状态的实例对象。
- State: 状态接口,用来封装与上下文的一个特定状态所对应的行为。
- ConcreteState: 具体实现状态的类,每个类实现一个跟上下文相关的状态的具体处理。
3,示例代码
1 /** 2 * 封装与的一个特定状态相关的行为 3 */ 4 public interface State { 5 public void handle(String sampleParameter); 6 }
1 public class ConcreteStateA implements State { 2 3 @Override 4 public void handle(String sampleParameter) { 5 6 } 7 8 } 9 10 11 public class ConcreteStateB implements State { 12 13 @Override 14 public void handle(String sampleParameter) { 15 16 } 17 18 }
1 public class Context { 2 private State state; 3 4 public void setState(State state) { 5 this.state = state; 6 } 7 8 public void request(String sampleParameter) { 9 state.handle(sampleParameter); 10 } 11 12 }
4,实例代码
考虑一个用户在线投票引用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然用户同时也要取消他所投的票;
如果一个用户投的票次数超过8次,将进入黑名单,禁止在登录和使用系统
1 public interface VoteState { 2 3 public void vote(String user,String voteItem,VoteManager voteManger); 4 5 }
1 /** 2 * 正常投票 3 */ 4 public class NormalVoteState implements VoteState { 5 6 @Override 7 public void vote(String user, String voteItem, VoteManager voteManger) { 8 // TODO Auto-generated method stub 9 voteManger.getMapVote().put(user, voteItem); 10 System.out.println("恭喜你投票成功"); 11 } 12 13 } 14 15 16 /** 17 *重复投票 18 */ 19 public class RepeatVoteState implements VoteState { 20 21 @Override 22 public void vote(String user, String voteItem, VoteManager voteManger) { 23 System.out.println("请不要重复投票"); 24 } 25 26 } 27 28 29 /** 30 * 恶意投票 31 */ 32 public class SpiteVoteState implements VoteState { 33 34 @Override 35 public void vote(String user, String voteItem, VoteManager voteManger) { 36 String s = voteManger.getMapVote().get(user); 37 if(s != null) { 38 voteManger.getMapVote().remove(user); 39 } 40 41 System.out.println(user +" 你有恶意刷票行为,取消"+ voteItem +"投票资格"); 42 } 43 44 } 45 46 47 48 /** 49 *进入黑名单 50 */ 51 public class BlackVoteState implements VoteState { 52 53 @Override 54 public void vote(String user, String voteItem, VoteManager voteManger) { 55 // TODO Auto-generated method stub 56 57 System.out.println(user + " 进入黑名单,将禁止登陆和使用本系统"); 58 59 } 60 61 }
1 public class VoteManager { 2 3 private VoteState state = null; 4 5 private Map<String ,String > mapVote = new HashMap<String,String>(); 6 private Map<String,Integer> mapVoteCount = new HashMap<String ,Integer>(); 7 8 public Map<String,String> getMapVote() { 9 return mapVote; 10 } 11 12 public void vote(String user,String voteItem) { 13 Integer oldVOteCount = mapVoteCount.get(user); 14 if(null == oldVOteCount) { 15 oldVOteCount = 0; 16 } 17 oldVOteCount = oldVOteCount +1; 18 mapVoteCount.put(user, oldVOteCount); 19 20 if(oldVOteCount == 1) { 21 // TODO 正常的状态 22 state = new NormalVoteState(); 23 } else if(oldVOteCount>1 && oldVOteCount<5) { 24 // TODO 重复投票 25 state = new RepeatVoteState(); 26 27 } else if (oldVOteCount>=5 && oldVOteCount<8) { 28 //TODO 恶意投票 29 state = new SpiteVoteState(); 30 } else if(oldVOteCount >= 8) { 31 // TODO 进入黑名单 32 state = new BlackVoteState(); 33 } 34 state.vote(user, voteItem, this); 35 } 36 }
1 public class Client { 2 public static void main(String[] args) { 3 VoteManager voteManager = new VoteManager(); 4 for(int i =0;i<8;i++) { 5 voteManager.vote("xiaoming","明天会下雨吗?"); 6 } 7 8 } 9 10 }
5,状态和行为
所谓对象的状态,通常指的就是对象实例的属性的值;而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上。
状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应的不同功能。
6,状态模式优缺点
优点:
-
- 简化引用逻辑控制
- 更好地分离状态和行为
- 更好的扩展
- 显式化进行状态转换
缺点:
-
- 一个状态对应一个状态处理类,会使得程序引入太多的状态类,这样程序变得杂乱。
- 一个状态对应一个状态处理类,会使得程序引入太多的状态类,这样程序变得杂乱。
7,状态模式的本质
状态模式的本质:根据状态来分离和选择行为。 |
8,何时选用状态模式
- 如果一个对象的行为取决于它的状态,而且它必须在运行时刻根据状态来改变的行为,可以使用状态模式,来把状态和行为分离开。虽然分离开了,但状态和行为是有对应关系的,可以在运行期间,通过改变状态,就能够调用到该状态对应的状态处理对象上去,从而改变对象的行为。
- 如果一个操作中包含有庞大的多分支语句,而且这些分支依赖于对象的状态,可以使用状态模式,把各个分支的处理分散包装到单独的对象处理类中,这样,就些分支对应的对象就可以不依赖于其他对象而独立变化