一、状态模式定义

1.状态模式也称为状态机模式,是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类,属于行为型模式

2.状态模式中类的行为是由状态决定的,不同的状态下有不同的行为。其意图是让一个对象在其内部改变的时候,其行为也随之改变。状态模式核心是状态与行为绑定,不同的状态对应不同的行为

3.状态模式的应用场景:

  A.行为随状态改变而改变的场景

  B.一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态

二、状态模式示例

1.状态模式一般包含三种角色:

  A.环境类角色(Context):定义客户端需要的接口,内部维护一个当前状态实例,并负责具体状态的切换

  B.抽象状态角色(State):定义该状态下的行为,可以有一个或多个行为

  C.具体状态角色(ConcreteState):具体实现该状态对应的行为,并且在需要的情况下进行状态切换

2.代码示例

 1 public class AppContext {
 2 
 3     public static final UserState STATE_LOGIN = new LoginState();
 4     public static final UserState STATE_UNLOGIN = new UnLoginState();
 5 
 6     private UserState currentState = STATE_UNLOGIN;
 7 
 8     {
 9         STATE_LOGIN.setContext(this);
10         STATE_UNLOGIN.setContext(this);
11     }
12 
13     public void setState(UserState state){
14         this.currentState = state;
15     }
16 
17     public UserState getState(){
18         return this.currentState;
19     }
20 
21     public void favorite(){
22         this.currentState.favorite();
23     }
24 
25     public void comment(String comment){
26         this.currentState.comment(comment);
27     }
28 }
29 
30 public abstract class UserState {
31     protected AppContext context;
32 
33     public void setContext(AppContext context) {
34         this.context = context;
35     }
36 
37     public abstract void favorite();
38 
39     public abstract void comment(String comment);
40 }
41 
42 public class LoginState extends UserState {
43     @Override
44     public void favorite() {
45         System.out.println("收藏成功!");
46     }
47 
48     @Override
49     public void comment(String comment) {
50         System.out.println(comment);
51     }
52 }
53 
54 public class UnLoginState extends UserState {
55 
56     @Override
57     public void favorite() {
58         this.switch2login();
59         this.context.getState().favorite();
60     }
61 
62     @Override
63     public void comment(String comment) {
64         this.switch2login();
65         this.context.getState().comment(comment);
66     }
67 
68     private void switch2login(){
69         System.out.println("跳转到登录页!");
70         this.context.setState(this.context.STATE_LOGIN);
71     }
72 }
73 
74 public class Test {
75     public static void main(String[] args) {
76         AppContext context = new AppContext();
77         context.favorite();
78         context.comment("评论:好文章,360个赞");
79     }
80 }

3.状态模式的优缺点

  A.优点

    a.结构清晰:将状态独立为类,消除了冗余的if...else或switch...case语句,代码更加简洁,提高系统可维护性

    b.将状态转换显示化:通常的对象内部都是使用数值类型来定义状态,状态的切换是通过赋值进行表现,不够直观;而使用状态类,在切换状态时,是以不同的类进行表示,转化目的更加明确

    c.状态类职责明确且具备扩展性

  B.缺点

    a.类膨胀:如果一个事物具备很多状态,则会造成状态类太多

    b.状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码结构的混乱

    c.状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源代码