本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.youkuaiyun.com/csh624366188
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。看起来,状态模式好像是神通广大很厉害似的——居然能够“修改自身的类”!下面让我们一起来看一下他的厉害吧!
适用场景:
状态模式主要解决的是当控制一个对象状态装换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判 断逻辑简单化。当一个对象行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
要点:
1. 策略模式和状态模式是双胞胎,它们有相同的类图,但是它们的意图不同。策略模式是围绕可以互换的算法来成功创建业务的,然而状态模式是通过改变对象内部的状态来帮助对象控制自己的行为.
2. Context将与状态相关的操作委托给当前的Concrete State对象处理。
3. Context可将自身作为一个参数传递给处理该请求的状态对象。这使得状态对象在必要时可访问Context。
4. Context或Concrete State类都可决定哪个状态是另外哪一个的后继者,以及是在何种条件下进行状态转换。也就是说可以在State中保存对Concrete State的引用,在必要时设置具体的状态,做到状态的转换。
5. 一般来讲,当状态转换是固定的时候,状态转换就适合放在Context中。然而,当转换是更动态的时候,通常会放到具体的状态类中进行。(具体状态类持有Context的引用,实现状态的转换)
Context类:维护一个ConcreteState子类的一个实例,这个实例定义当前的状态。
State类:抽象状态类,定义一个 接口以封装与Context的一个特定状态相关的行为。
ConcreteStateA,ConcreteStateB类:具体状态类,每一个子 类实现一个与Context的一个状态相关的行为。
具体实现:
先定义接口UserState
- 1 public interface UserState {
- 2 public UserService userService = new UserService();
- 3 // 状态为0代表普通用户,这些状态主要用于持久化到数据
- 4 public final static int COMMON_STATUS = 0;
- 5 // 状态为1代表待审核用户
- 6 public final static int FOR_VERIFY_STATUS = 1;
- 7 // 状态为2是代表vip用户
- 8 public final static int VIP_STATUS = 2;
- 9
- 10 // 提交信息
- 11 public void submit() throws Exception;
- 12
- 13 // 审核没通过
- 14 public void rollback() throws Exception;
- 15
- 16 // 审核通过
- 17 public void pass() throws Exception;
- 18
- 19 public int getStatus();
代表各个状态的类
未提交信息的用户NotSubmitUser.java
- 2 public class NotSubmitUser implements UserState {
- 3 public void pass() throws Exception {
- 4 throw new Exception("no support method");
- 5 }
- 6
- 7 public void rollback() throws Exception {
- 8 throw new Exception("no support method");
- 9 }
- 10
- 11 public void submit() throws Exception {
- 12 User user = userService.getUser(0);
- 13 user.setStauts(FOR_VERIFY_STATUS);
- 14 userService.update(user);
- 15 }
- 16
- 17 public int getStatus() {
- 18 return COMMON_STATUS;
- 19 }
- 20 }
待审核的用户WaitForVerifyUser.java
- 22 public class WaitForVerifyUser implements UserState {
- 23
- 24 public void pass() throws Exception {
- 25 User user = userService.getUser(0);
- 26 user.setStauts(VIP_STATUS);
- 27 userService.update(user);
- 28 }
- 29
- 30 public void rollback() throws Exception {
- 31 User user = userService.getUser(0);
- 32 user.setStauts(COMMON_STATUS);
- 33 userService.update(user);
- 34 }
- 35
- 36 public void submit() throws Exception {
- 37 throw new Exception("no support method");
- 38 }
- 39
- 40 public int getStatus() {
- 41 return VIP_STATUS;
- 42 }
- 43 }
审核通过的用户,vip VipUser.java
- 45 public class VipUser implements UserState {
- 46
- 47 public void pass() throws Exception {
- 48 throw new Exception("no support method");
- 49 }
- 50
- 51 public void rollback() throws Exception {
- 52 User user = userService.getUser(0);
- 53 user.setStauts(COMMON_STATUS);
- 54 userService.update(user);
- 55 }
- 56
- 57 public void submit() throws Exception {
- 58 throw new Exception("no support method");
- 59 }
- 60
- 61 public int getStatus() {
- 62 return FOR_VERIFY_STATUS;
- 63 }
- 64 }
根据用户的status的返回不同的UserState
- 66 public class UserStateFactory {
- 67 static List list = null;
- 68 static {
- 69 list = new ArrayList();
- 70 list.add(new NotSubmitUser());
- 71 list.add(new VipUser());
- 72 list.add(new WaitForVerifyUser());
- 73
- 74 }
- 75
- 76 public static UserState getUserState(int status) {
- 77 for (UserState state : list) {
- 78 if (state.getStatus() == status)
- 79 return state;
- 80 }
- 81 return null;
- 82 }
- 83 }
状态模式操作是固定的,但是接受者类不相同。多态性的原则实际执行哪个方法不仅取决与方法签名,还取决与操作的接受者类。
该例子只是state模式的一个场景的应用,比较具体。
状态模式的优点:
1.非常好的扩展性---假设增加一个用户组:当vip用户的信用达到一定程度后,升级到永久的vip。这时只需另外添加一个状态类,对原来的代码并不需要做改动。
2.代码结构清晰,不同出错。即程序健壮--除UserStateFactory的getUserState(int status)外,其他方法的逻辑非常的简单,都不包含局部变量。如果程序不需要持久化到数据库,也不需要getUserState(int status),该方法是状态模式内容之外的 。用状态模式类的数量会大大的增加。
说明:该例子只是状态模式的一个应用,并不是状态模式,是属于比较具体