Oh!Coder

Coding Life

Objective C--状态模式

| Comments

今天想和大家分享的是状态模式。关于状态模式理解起来不是很难,而且这个模式主要解决的目的也很明确。好的,还是先给出定义吧。

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

其实,状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。说白了,目的就是为了消除庞大的条件分支语句。

这次想通过一个具体的例子,和大家一起学习状态模式。例子的内容是一天不同时间段内,不同的状态。时间是不同状态之间的分割点。

好的,下面还是先给出这个例子的类结构图。

pic

上面的类结构图并不复杂,首先是抽象出一个状态的父类,通过工作类对时间点的设置来切换不同的状态。

逻辑结构并不复杂,还是给出简易的代码,大家可以慢慢体会一下。

注意:本文所有代码均在ARC环境下编译通过。

  • 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类接口
1
2
3
4
5
 
#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
#import "SleepingState.h"
#import "Work.h"

@implementation SleepingState
-(void)WriteProgram:(Work *)w{
    NSLog(@"当前时间:%f点不行了,睡着了", [w Hour]);
}
@end
  • RestState类接口
1
2
3
4
5
6
7
8
#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的子类之间,来减少相互间的依赖。当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

Comments