美文网首页
iOS设计模式之状态模式下

iOS设计模式之状态模式下

作者: 点滴86 | 来源:发表于2024-06-26 23:35 被阅读0次

状态机实现方式三:状态模式

在查表法的代码实现中,事件触发的动作只是简单的积分加减,所以可以用一个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

相关文章

网友评论

      本文标题:iOS设计模式之状态模式下

      本文链接:https://www.haomeiwen.com/subject/jynscjtx.html