状态模式(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的子类之间,来减少相互间的依赖。当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。