狀態模式(State),當一個對象的內在狀態改變時允許改變其行爲,這個對象看起來像是改變了其類。
其實,狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把複雜的判斷邏輯簡化。說白了,目的就是爲了消除龐大的條件分支語句。
這次想通過一個具體的例子,和大家一起學習狀態模式。例子的內容是一天不同時間段內,不同的狀態。時間是不同狀態之間的分割點。
好的,下面還是先給出這個例子的類結構圖。
上面的類結構圖並不複雜,首先是抽象出一個狀態的父類,通過工作類對時間點的設置來切換不同的狀態。
邏輯結構並不複雜,還是給出簡易的代碼,大家可以慢慢體會一下。
-
Work類接口
1
2
3
4
5
6
7
8
9
10
11
|
#import
<Foundation/Foundation.h> @class
State; @interface
Work : NSObject { State
*current; } @property
double
Hour; @property
BOOL
TaskFinished; -( void )SetState:(State*)s; -( void )WriteProgram; @end |
-
Work類實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#import
"Work.h" #import
"State.h" #import
"ForenoonState.h" @implementation
Work @synthesize
Hour =_Hour; @synthesize
TaskFinished =_TaskFinished; -( id )init{ if
( self
== [superinit]) { current=
[[ForenoonState alloc]init]; } return
self ; } -( void )SetState:(State
*)s{ current
= s; } -( void )WriteProgram{ [current
WriteProgram: self ]; } @end |
-
State類接口
1
2
3
4
5
6
|
#import
<Foundation/Foundation.h> @class
Work; @interface
State: NSObject -( void )WriteProgram:(Work*)w; @end |
-
State類實現
1
2
3
4
5
6
7
8
9
|
#import
"State.h" #import
"Work.h" @implementation
State -( void )WriteProgram:(Work
*)w{ NSLog (@ "當前時間:%f點下班回家了" ,[w
Hour]); } @end |
-
ForenoonState類接口
#import "State.h"
@interface ForenoonState :State
@end
-
ForenoonState類實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#import
"ForenoonState.h" #import
"Work.h" #import
"NoonState.h" @implementation
ForenoonState -( void )WriteProgram:(Work
*)w{ if
([w Hour] < 12) { NSLog (@ "當前時間:%f點上午工作,精神百倍" ,
[w Hour]); } else
{ [w
SetState:[NoonState new ]]; [w
WriteProgram]; } } @end |
-
NoonState類接口
1
2
3
4
|
#import
"State.h" @interface
NoonState:State @end |
-
NoonState類實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#import
"NoonState.h" #import
"Work.h" #import
"AfternoonState.h" @implementation
NoonState -( void )WriteProgram:(Work
*)w{ if ([w
Hour] <13) NSLog (@ "當前時間:%f點餓了,午飯;犯困,午休" ,[w
Hour]); else
{ [w
SetState:[[AfternoonState alloc]init]]; [w
WriteProgram]; } } @end |
-
AfternoonState類接口
1
2
3
4
|
#import
"State.h" @interface
AfternoonState :State @end |
-
AfternoonState類實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#import
"AfternoonState.h" #import
"Work.h" #import
"EveningState.h" @implementation
AfternoonState -( void )WriteProgram:(Work
*)w{ if
([w Hour] <17) { NSLog (@ "當前時間:%f點下午狀態還不錯,繼續努力" ,
[w Hour]); } else
{ [w
SetState:[[EveningState alloc]init]]; [w
WriteProgram]; } } @end |
-
EveningState類接口
1
2
3
4
|
#import
"State.h" @interface
EveningState:State @end |
-
EveningState類實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#import
"EveningState.h" #import
"Work.h" #import
"RestState.h" #import
"SleepingState.h" @implementation
EveningState -( void )WriteProgram:(Work
*)w{ if
([w TaskFinished]) { [w
SetState:[[RestState alloc]init]]; [w
WriteProgram]; } else
{ if ([w
Hour] <21) NSLog (@ "當前時間:%f點加班哦,疲憊之極" ,
[w Hour]); else
{ [w
SetState:[[SleepingState alloc]init]]; [w
WriteProgram]; } } } @end |
=============================================
-
SleepingState類接口
1
2
3
4
|
#import
"State.h" @interface
SleepingState :State @end |
-
SleepingState類實現
1
2
3
4
5
6
7
8
9
|
#import
"SleepingState.h" #import
"Work.h" @implementation
SleepingState -( void )WriteProgram:(Work
*)w{ NSLog (@ "當前時間:%f點不行了,睡着了" ,
[w Hour]); } @end |
-
RestState類接口
1
2
3
4
|
#import
"State.h" @interface
RestState:State @end |
-
RestState類實現
1
2
3
4
5
6
7
8
9
|
#import
"RestState.h" #import
"Work.h" @implementation
RestState -( void )WriteProgram:(Work
*)w{ NSLog (@ "當前時間:%f點下班回家了" ,
[w Hour]); } @end |
-
Main方法調用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#import
<Foundation/Foundation.h> #import
"Work.h" int
main ( int
argc, const
char
*argv[]) { @autoreleasepool { Work
*emergencyProjects = [[Work alloc]init]; [emergencyProjects
setHour:9]; [emergencyProjects
WriteProgram]; [emergencyProjects
setHour:10]; [emergencyProjects
WriteProgram]; [emergencyProjects
setHour:12]; [emergencyProjects
WriteProgram]; [emergencyProjects
setHour:13]; [emergencyProjects
WriteProgram]; [emergencyProjects
setHour:14]; [emergencyProjects
WriteProgram]; [emergencyProjects
setHour:17]; [emergencyProjects
WriteProgram]; [emergencyProjects
setTaskFinished: NO ]; [emergencyProjects
setHour:19]; [emergencyProjects
WriteProgram]; [emergencyProjects
setHour:22]; [emergencyProjects
WriteProgram]; } return
0; } |
上面是用Objective C語言實現的簡單代碼。
通過這個例子,可以看到,狀態模式通過把各種狀態轉移邏輯分佈到State的子類之間,來減少相互間的依賴。當一個對象的行爲取決於它的狀態,並且它必須在運行時刻根據狀態改變它的行爲時,就可以考慮使用狀態模式了。