状态模式结构:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace DesignPattern.BehavioralPattern
8 {
9 #region 状态模式要点
10 //要点:允许一个对象再起内部状态改变是自动变化其行为,对象看起来就像是改变了它的类。
11 //
12 //使用场景:
13 //1.根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的情况下。
14 //2.某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式。
15 //3.当相似状态和基于条件的状态机转换中存在许多重复代码时, 可使用状态模式。
16 /*
17 * 实现方式:
18 1. 确定哪些类是上下文。
19 它可能是包含依赖于状态的代码的已有类;
20 如果特定于状态的代码分散在多个类中, 那么它可能是一个新的类。
21
22 2.声明状态接口。
23 虽然你可能会需要完全复制上下文中声明的所有方法,最好把关注点放在可能包含特定于状态的行为的方法上。
24
25 3.为每个实际状态创建一个继承于状态接口的类。然后检查上下文中的方法并将与特定状态相关的所有代码抽取到新建的类中。
26 在将代码移动到状态类的过程中, 你可能会发现它依赖于上下文中的一些私有成员。
27 你可以采用以下几种变通方式:
28
29 *将这些成员变量或方法设为公有。
30 *将需要抽取的上下文行为更改为上下文中的公有方法, 然后在状态类中调用。这种方式简陋却便捷,你可以稍后再对其进行修补。
31 *将状态类嵌套在上下文类中。 这种方式需要你所使用的编程语言支持嵌套类。
32
33 4.在上下文类中添加一个状态接口类型的引用成员变量, 以及一个用于修改该成员变量值的公有设置器。
34
35 5.再次检查上下文中的方法, 将空的条件语句替换为相应的状态对象方法,设置默认状态。
36
37 6.为切换上下文状态, 你需要创建某个状态类实例并将其传递给上下文。
38 你可以在上下文、 各种状态或客户端中完成这项工作。无论在何处完成这项工作, 该类都将依赖于其所实例化的具体类。
39
40 */
41 #endregion
42
43
44 //状态 (State) 接口会声明特定于状态的方法。
45 //这些方法应能被其他所有具体状态所理解, 因为你不希望某些状态所拥有的方法永远不会被调用。
46 public abstract class AbstractStatePattern
47 {
48 protected Context _context;
49 public void SetContext(Context context)
50 {
51 _context = context;
52 }
53
54 public abstract void Handle1();
55 public abstract void Handle2();
56 }
57
58
59 public class StateNone : AbstractStatePattern
60 {
61 public override void Handle1()
62 {
63 Console.WriteLine("StateNone 不执行任何操作");
64 }
65
66 public override void Handle2()
67 {
68 Console.WriteLine("StateNone 不执行任何操作");
69 }
70 }
71
72
73 //具体状态 (Concrete States) 会自行实现特定于状态的方法。
74 //为了避免多个状态中包含相似代码, 你可以提供一个封装有部分通用行为的中间抽象类。
75 //状态对象可存储对于上下文对象的反向引用。状态可以通过该引用从上下文处获取所需信息,并且能触发状态转移。
76 public class StateOne : AbstractStatePattern
77 {
78 public override void Handle1()
79 {
80 Console.WriteLine("当前状态StateOne");
81 Console.WriteLine("StateOne 执行操作切换至 StateTwo");
82 _context.TransformToState(new StateTwo());
83 }
84
85
86
87 public override void Handle2()
88 {
89 Console.WriteLine("StateOne 不执行任何操作");
90 }
91 }
92
93
94 public class StateTwo : AbstractStatePattern
95 {
96 public override void Handle1()
97 {
98 Console.WriteLine("StateTwo 不执行任何操作");
99 }
100
101 //上下文和具体状态都可以设置上下文的下个状态, 并可通过替换连接到上下文的状态对象来完成实际的状态转换。
102 public override void Handle2()
103 {
104 Console.WriteLine("当前状态StateTwo");
105 Console.WriteLine("StateTwo 执行操作切换至 StateOne");
106 _context.TransformToState(new StateOne());
107 }
108 }
109
110
111 //上下文 (Context) 保存了对于一个具体状态对象的引用,并会将所有与该状态相关的工作委派给它。
112 //上下文通过状态接口与状态对象交互, 且会提供一个设置器用于传递新的状态对象。
113 public class Context
114 {
115 AbstractStatePattern _state = new StateNone();
116
117 public Context(AbstractStatePattern state)
118 {
119 TransformToState(state);
120 }
121
122 //上下文和具体状态都可以设置上下文的下个状态, 并可通过替换连接到上下文的状态对象来完成实际的状态转换。
123 public void TransformToState(AbstractStatePattern state)
124 {
125 _state = state;
126 _state.SetContext(this);
127 }
128
129 public void Handle1()
130 {
131 _state.Handle1();
132 }
133
134 public void Handle2()
135 {
136 _state.Handle2();
137 }
138 }
139
140
141 public class StatePatternClient
142 {
143 public static void Test()
144 {
145 Context context = new Context(new StateOne());
146
147 context.Handle1();
148 context.Handle2();
149 }
150 }
151 }