状态机实现方式三:状态模式
在查表法的代码实现中,事件触发的动作只是简单的积分加减,所以可以用一个Number类型的二维数组mActionTable就能表示,二维数组中的值表示积分的加减值。但是如果要执行的动作并非这么简单,而是一系列复杂的逻辑操作(比如加减积分、写数据库、还有可能发送消息通知等等),就没法用如此简单的二位数组来表示了。这也就是说,查表法的实现方式有一定局限性。
虽然分支逻辑的实现方式不存在这个问题,但它又存在上节讲到的其它问题,比如分支判断逻辑较多,代码代码可读性和可维护性不好等。实际上,针对分支逻辑法存在的问题,可以使用状态模式来解决。
状态模式通过将事件触发的状态转移和动作执行,拆分到不同的状态类中,来避免分支判断逻辑。代码如下:
typedef enum : NSInteger {
DMMarioStateSmall = 0,
DMMarioStateSuper,
DMMarioStateCape,
DMMarioStateFire,
} DMMarioState;
typedef enum : NSInteger {
DMMarioStateSmall = 0,
DMMarioStateSuper,
DMMarioStateCape,
DMMarioStateFire,
} DMMarioState;
@protocol DMMarioDelegate <NSObject>
- (DMMarioState)marioState;
- (void)obtainMushRoom;
- (void)obtainCape;
- (void)obtainFireFlower;
- (void)meetMonster;
@end
@interface DMMarioStateMachine : NSObject
@property (nonatomic, assign) NSInteger mScore;
- (void)setMario:(id<DMMarioDelegate>)mario;
- (DMMarioState)marioState;
- (void)obtainMushRoom;
- (void)obtainCape;
- (void)obtainFireFlower;
- (void)meetMonster;
@end
@interface DMMarioStateMachine ()
@property (nonatomic, strong) id<DMMarioDelegate> mMario;
@end
@implementation DMMarioStateMachine
- (instancetype)init
{
if (self = [super init]) {
DMSmallMario *smallMario = [[DMSmallMario alloc] initWithMarioStateMachine:self];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
self.mMario = mario;
self.mScore = 0;
}
return self;
}
- (void)setMario:(id<DMMarioDelegate>)mario
{
self.mMario = mario;
}
- (DMMarioState)marioState
{
return [self.mMario marioState];
}
- (void)obtainMushRoom
{
[self.mMario obtainMushRoom];
}
- (void)obtainCape
{
[self.mMario obtainCape];
}
- (void)obtainFireFlower
{
[self.mMario obtainFireFlower];
}
- (void)meetMonster
{
[self.mMario meetMonster];
}
@end
@interface DMSmallMario : NSObject <DMMarioDelegate>
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine;
@end
@interface DMSmallMario ()
@property (nonatomic, strong) DMMarioStateMachine *mMarioStateMachine;
@end
@implementation DMSmallMario
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine
{
if (self = [super init]) {
self.mMarioStateMachine = marioStateMachine;
}
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateSmall;
}
- (void)obtainMushRoom
{
DMSuperMario *superMario = [[DMSuperMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)superMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore + 100;
}
- (void)obtainCape
{
DMCapeMario *capeMario = [[DMCapeMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)capeMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore + 200;
}
- (void)obtainFireFlower
{
DMFireMario *fireMario = [[DMFireMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)fireMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore + 300;
}
- (void)meetMonster
{
// do nothing
}
@end
@interface DMSuperMario : NSObject
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine;
@end
@interface DMSuperMario ()
@property (nonatomic, strong) DMMarioStateMachine *mMarioStateMachine;
@end
@implementation DMSuperMario
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine
{
if (self = [super init]) {
self.mMarioStateMachine = marioStateMachine;
}
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateSuper;
}
- (void)obtainMushRoom
{
// do nothing
}
- (void)obtainCape
{
DMCapeMario *capeMario = [[DMCapeMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)capeMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore + 200;
}
- (void)obtainFireFlower
{
DMFireMario *fireMario = [[DMFireMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)fireMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore + 300;
}
- (void)meetMonster
{
DMSmallMario *smallMario = [[DMSmallMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore - 100;
}
@end
@interface DMCapeMario : NSObject
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine;
@end
@interface DMCapeMario ()
@property (nonatomic, strong) DMMarioStateMachine *mMarioStateMachine;
@end
@implementation DMCapeMario
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine
{
if (self = [super init]) {
self.mMarioStateMachine = marioStateMachine;
}
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateCape;
}
- (void)obtainMushRoom
{
// do nothing
}
- (void)obtainCape
{
// do nothing
}
- (void)obtainFireFlower
{
// do nothing
}
- (void)meetMonster
{
DMSmallMario *smallMario = [[DMSmallMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore - 200;
}
@end
@interface DMFireMario : NSObject
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine;
@end
@interface DMFireMario ()
@property (nonatomic, strong) DMMarioStateMachine *mMarioStateMachine;
@end
@implementation DMFireMario
- (instancetype)initWithMarioStateMachine:(DMMarioStateMachine *)marioStateMachine
{
if (self = [super init]) {
self.mMarioStateMachine = marioStateMachine;
}
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateFire;
}
- (void)obtainMushRoom
{
// do nothing
}
- (void)obtainCape
{
// do nothing
}
- (void)obtainFireFlower
{
// do nothing
}
- (void)meetMonster
{
DMSmallMario *smallMario = [[DMSmallMario alloc] initWithMarioStateMachine:self.mMarioStateMachine];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
[self.mMarioStateMachine setMario:mario];
self.mMarioStateMachine.mScore = self.mMarioStateMachine.mScore - 300;
}
@end
DMMarioStateMachine和各个状态类之前是双向依赖关系。DMMarioStateMachine依赖各个状态类是理所当然的,但是反过来,各个状态类为什么要依赖DMMarioStateMachine呢?这是因为,各个状态类要更新DMMarioStateMachine中的两个变量mMario和mScore。
上面的代码还可以继续优化,可以将状态类设计成单例,毕竟状态类中不包含任何成员变量。代码如下:
@class DMMarioStateMachine;
@protocol DMMarioDelegate <NSObject>
- (DMMarioState)marioState;
- (void)obtainMushRoom:(DMMarioStateMachine *)marioStateMachine;
- (void)obtainCape:(DMMarioStateMachine *)marioStateMachine;
- (void)obtainFireFlower:(DMMarioStateMachine *)marioStateMachine;
- (void)meetMonster:(DMMarioStateMachine *)marioStateMachine;
@end
@interface DMMarioStateMachine : NSObject
@property (nonatomic, assign) NSInteger mScore;
- (void)setMario:(id<DMMarioDelegate>)mario;
- (DMMarioState)marioState;
- (void)obtainMushRoom;
- (void)obtainCape;
- (void)obtainFireFlower;
- (void)meetMonster;
@end
@interface DMMarioStateMachine ()
@property (nonatomic, strong) id<DMMarioDelegate> mMario;
@end
@implementation DMMarioStateMachine
- (instancetype)init
{
if (self = [super init]) {
DMSmallMario *smallMario = [DMSmallMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
self.mMario = mario;
self.mScore = 0;
}
return self;
}
- (void)setMario:(id<DMMarioDelegate>)mario
{
self.mMario = mario;
}
- (DMMarioState)marioState
{
return [self.mMario marioState];
}
- (void)obtainMushRoom
{
[self.mMario obtainMushRoom:self];
}
- (void)obtainCape
{
[self.mMario obtainCape:self];
}
- (void)obtainFireFlower
{
[self.mMario obtainFireFlower:self];
}
- (void)meetMonster
{
[self.mMario meetMonster:self];
}
@end
@interface DMSmallMario : NSObject <DMMarioDelegate, NSCopying>
+ (DMSmallMario *)sharedSingleton;
@end
static DMSmallMario *_smallMario = nil;
@implementation DMSmallMario
+ (DMSmallMario *)sharedSingleton
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_smallMario = [[super allocWithZone:NULL] init];
});
return _smallMario;
}
// 重写方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
return [self sharedSingleton];
}
// 重写方法
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateSmall;
}
- (void)obtainMushRoom:(DMMarioStateMachine *)marioStateMachine
{
DMSuperMario *superMario = [DMSuperMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)superMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore + 100;
}
- (void)obtainCape:(DMMarioStateMachine *)marioStateMachine
{
DMCapeMario *capeMario = [DMCapeMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)capeMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore + 200;
}
- (void)obtainFireFlower:(DMMarioStateMachine *)marioStateMachine
{
DMFireMario *fireMario = [DMFireMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)fireMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore + 300;
}
- (void)meetMonster:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
@end
@interface DMSuperMario : NSObject <DMMarioDelegate, NSCopying>
+ (DMSuperMario *)sharedSingleton;
@end
static DMSuperMario *_superMario = nil;
@implementation DMSuperMario
+ (DMSuperMario *)sharedSingleton
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_superMario = [[super allocWithZone:NULL] init];
});
return _superMario;
}
// 重写方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
return [self sharedSingleton];
}
// 重写方法
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateSuper;
}
- (void)obtainMushRoom:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)obtainCape:(DMMarioStateMachine *)marioStateMachine
{
DMCapeMario *capeMario = [DMCapeMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)capeMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore + 200;
}
- (void)obtainFireFlower:(DMMarioStateMachine *)marioStateMachine
{
DMFireMario *fireMario = [DMFireMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)fireMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore + 300;
}
- (void)meetMonster:(DMMarioStateMachine *)marioStateMachine
{
DMSmallMario *smallMario = [DMSmallMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore - 100;
}
@end
@interface DMCapeMario : NSObject <DMMarioDelegate, NSCopying>
+ (DMCapeMario *)sharedSingleton;
@end
static DMCapeMario *_capeMario = nil;
@implementation DMCapeMario
+ (DMCapeMario *)sharedSingleton
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_capeMario = [[super allocWithZone:NULL] init];
});
return _capeMario;
}
// 重写方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
return [self sharedSingleton];
}
// 重写方法
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateCape;
}
- (void)obtainMushRoom:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)obtainCape:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)obtainFireFlower:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)meetMonster:(DMMarioStateMachine *)marioStateMachine
{
DMSmallMario *smallMario = [DMSmallMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore - 200;
}
@end
@interface DMFireMario : NSObject <DMMarioDelegate, NSCopying>
+ (DMFireMario *)sharedSingleton;
@end
static DMFireMario *_fireMario = nil;
@implementation DMFireMario
+ (DMFireMario *)sharedSingleton
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_fireMario = [[super allocWithZone:NULL] init];
});
return _fireMario;
}
// 重写方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
return [self sharedSingleton];
}
// 重写方法
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (DMMarioState)marioState
{
return DMMarioStateFire;
}
- (void)obtainMushRoom:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)obtainCape:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)obtainFireFlower:(DMMarioStateMachine *)marioStateMachine
{
// do nothing
}
- (void)meetMonster:(DMMarioStateMachine *)marioStateMachine
{
DMSmallMario *smallMario = [DMSmallMario sharedSingleton];
id<DMMarioDelegate> mario = (id<DMMarioDelegate>)smallMario;
[marioStateMachine setMario:mario];
marioStateMachine.mScore = marioStateMachine.mScore - 300;
}
@end
网友评论