012 --- 第16章 状态模式

简述:

  状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

  状态模式包括:抽象状态类、具体状态类、具体状态维护类

    抽象状态类:定义一个接口以封装与具体状态维护类的一个特定状态相关的行为。

    具体状态类:每一个子类实现一个与具体状态维护类的一个状态相关的行为。

 

应用场景:将特定状相关的行为局部化,消除庞大的分支语句

 

注:开发环境调整为VS2017,操作系统win11

 

状态模式代码:

 

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 
 6 // 状态模式
 7 class CContext;
 8 // 抽象状态类
 9 class CState
10 {
11 public:
12     string m_szName;
13     CState() : m_szName("") {}
14     virtual void Handle(CContext* pContext) = 0;
15 };
16 
17 // 具体状态维护类
18 class CContext
19 {
20 private:
21     CState* m_pState;
22 
23 public:
24     CContext(CState* pState) { m_pState = pState; }
25 
26     void SetState(CState* pState) 
27     { 
28         m_pState = pState; 
29         cout << "当前的状态:" << m_pState->m_szName << endl;
30     }
31     CState* GetState() { return m_pState; }
32 
33     void Request(){ m_pState->Handle(this); }
34 };
35 
36 // 具体状态类
37 class CConcreteStateA : public CState
38 {
39 public:
40     CState* m_pConcreteStateB;
41     
42 public:
43     CConcreteStateA() 
44     {
45         m_szName = "A";
46         m_pConcreteStateB = NULL;
47     }
48 
49     virtual void Handle(CContext* pContext)
50     {
51         pContext->SetState(m_pConcreteStateB);
52     }
53 };
54 
55 // 具体状态类
56 class CConcreteStateB : public CState
57 {
58 public:
59     CState* m_pConcreteStateA;
60 
61 public:
62     CConcreteStateB()
63     {
64         m_pConcreteStateA = NULL;
65         m_szName = "B";
66     }
67 
68     virtual void Handle(CContext* pContext)
69     {
70         pContext->SetState(m_pConcreteStateA);
71     }
72 };
73 
74 int main()
75 {
76     CConcreteStateA ConcreteStateA;
77     CConcreteStateB ConcreteStateB;
78     ConcreteStateA.m_pConcreteStateB = &ConcreteStateB;
79     ConcreteStateB.m_pConcreteStateA = &ConcreteStateA;
80     CContext Context(&ConcreteStateA);
81     Context.Request();
82     Context.Request();
83     Context.Request();
84     Context.Request();
85     system("pause");
86     return 0;
87 }

运行结果:

 

 

 

例:不同时间点工作状态

代码如下:

 

  1 #include <iostream>
  2 #include <string>
  3 using namespace std;
  4 
  5 
  6 class CWork;
  7 // 抽象状态类
  8 class CState
  9 {
 10 public:
 11     virtual  void WriteProgram(CWork* pWork) = 0;
 12 };
 13 
 14 // 工作类(具体状态维护类)
 15 class CWork
 16 {
 17 private:
 18     CState* m_pCurrentState;
 19     int m_nHour;
 20     bool m_bFinished;
 21 
 22 public:
 23     CWork(CState* pState) : m_nHour(0), m_bFinished(false)
 24     {
 25         m_pCurrentState = pState;
 26     }
 27 
 28     void SetTime(int nHour)
 29     {
 30         m_nHour = nHour;
 31     }
 32 
 33     int GetTime()
 34     {
 35         return m_nHour;
 36     }
 37 
 38     void SetState(CState* pState)
 39     {
 40         m_pCurrentState = pState;
 41     }
 42 
 43     void SetTaskFinished(bool bFinished)
 44     {
 45         m_bFinished = bFinished;
 46     }
 47 
 48     bool GetTaskFinished()
 49     {
 50         return m_bFinished;
 51     }
 52 
 53     void WriteProgram()
 54     {
 55         m_pCurrentState->WriteProgram(this);
 56     }
 57 };
 58 
 59 // 具体状态类
 60 class CForenoonState : public CState
 61 {
 62 public:
 63     CState* m_pNoonState;
 64 public:
 65     virtual void WriteProgram(CWork* pWork)
 66     {
 67         if (pWork->GetTime() < 12)
 68             cout << "当前时间[" << pWork->GetTime() << "]点,上午工作,精神百倍。" << endl;
 69         else
 70         {
 71             pWork->SetState(m_pNoonState);
 72             pWork->WriteProgram();
 73         }
 74     }
 75 };
 76 
 77 // 具体状态类
 78 class CNoonState : public CState
 79 {
 80 public:
 81     CState* m_pAfterNoonState;
 82 public:
 83     virtual void WriteProgram(CWork* pWork)
 84     {
 85         if (pWork->GetTime() < 13)
 86             cout << "当前时间[" << pWork->GetTime() << "]点,午饭,犯困,午休。" << endl;
 87         else
 88         {
 89             pWork->SetState(m_pAfterNoonState);
 90             pWork->WriteProgram();
 91         }
 92     }
 93 };
 94 
 95 // 具体状态类
 96 class CAfterNoonState : public CState
 97 {
 98 public:
 99     CState* m_pEveningState;
100 public:
101     virtual void WriteProgram(CWork* pWork)
102     {
103         if (pWork->GetTime() < 17)
104             cout << "当前时间[" << pWork->GetTime() << "]点,下午状态还不错,继续努力。" << endl;
105         else
106         {
107             pWork->SetState(m_pEveningState);
108             pWork->WriteProgram();
109         }
110     }
111 };
112 
113 // 具体状态类
114 class CEveningState : public CState
115 {
116 public:
117     CState* m_pSleepingState;
118     CState* m_pRestState;
119 public:
120     virtual void WriteProgram(CWork* pWork)
121     {
122         if (pWork->GetTaskFinished())
123         {
124             pWork->SetState(m_pRestState);
125             pWork->WriteProgram();
126         }
127         else
128         {
129             if (pWork->GetTime() < 21)
130                 cout << "当前时间[" << pWork->GetTime() << "]点,加班哦,疲惫之极。" << endl;
131             else
132             {
133                 pWork->SetState(m_pSleepingState);
134                 pWork->WriteProgram();
135             }
136         }
137     }
138 };
139 
140 // 具体状态类
141 class CSleepingState : public CState
142 {
143 public:
144     virtual void WriteProgram(CWork* pWork)
145     {
146         cout << "当前时间[" << pWork->GetTime() << "]点,不行了,睡着了。" << endl;
147     }
148 };
149 
150 // 具体状态类
151 class CRestState : public CState
152 {
153 public:
154     virtual void WriteProgram(CWork* pWork)
155     {
156         cout << "当前时间[" << pWork->GetTime() << "]点,下班回家了。" << endl;
157     }
158 };
159 
160 int main()
161 {
162     // C++的相互包含很微妙,不能像C#使用那么随意,可以用基类的指针实现,所以代码看起来比较冗余,也是我比较懒,没有对状态转换对象进行深入的处理。
163     // 同时我为了避免使用堆区变量,都用了栈区变量传指针的方式。
164     CForenoonState ForenoonState;
165     CNoonState NoonState;
166     CAfterNoonState AfterNoonState;
167     CEveningState EveningState;
168     CSleepingState SleepingState;
169     CRestState RestState;
170     ForenoonState.m_pNoonState = &NoonState;
171     NoonState.m_pAfterNoonState = &AfterNoonState;
172     AfterNoonState.m_pEveningState = &EveningState;
173     EveningState.m_pSleepingState = &SleepingState;
174     EveningState.m_pRestState = &RestState;
175 
176     CWork emergencyProjects(&ForenoonState);
177     emergencyProjects.SetTime(9);
178     emergencyProjects.WriteProgram();
179     emergencyProjects.SetTime(10);
180     emergencyProjects.WriteProgram();
181     emergencyProjects.SetTime(12);
182     emergencyProjects.WriteProgram();
183     emergencyProjects.SetTime(13);
184     emergencyProjects.WriteProgram();
185     emergencyProjects.SetTime(14);
186     emergencyProjects.WriteProgram();
187     emergencyProjects.SetTime(17);
188     //emergencyProjects.SetTaskFinished(true);
189     emergencyProjects.SetTaskFinished(false);
190     emergencyProjects.WriteProgram();
191     emergencyProjects.SetTime(19);
192     emergencyProjects.WriteProgram();
193     emergencyProjects.SetTime(22);
194     emergencyProjects.WriteProgram();
195     system("pause");
196     return 0;
197 }

输出结果:

 

posted @ 2020-08-26 14:25  二是一种不三不亖的范  阅读(173)  评论(0编辑  收藏  举报