状态模式:允许对象在内部状态改变时改变他们的行为,对象看起来就像修改他们的类。
状态模式是行为型模式之一。状态模式通过改变对象内部的状态来控制自己的行为。
策略模式和状态模式很相似,只是侧重点不同。策略模式通过替换算法来改变行为。状态模式是根据状态来驱动行为。
举个栗子
有一个糖果机 ,投币后,然后摇动拉杆等待片刻就会出来糖果。
总的来说会有如下几个状态
1.未投币状态
2.已投币状态
3.出糖果状态
4.无货状态
状态类
#import <Foundation/Foundation.h>
@class SweetMaichine;
NS_ASSUME_NONNULL_BEGIN
@interface State : NSObject
@property (nonatomic ,strong)SweetMaichine * machine;
-(void)insertQuarter;
-(void)enjectCuarter;
-(void)turnCrank;
-(void)dispends;
+(instancetype)new UNAVAILABLE_ATTRIBUTE;
-(instancetype)init UNAVAILABLE_ATTRIBUTE;
-(instancetype)initWithSweetMaichine:(SweetMaichine *)machine;
@end
NS_ASSUME_NONNULL_END
默认状态的实现 ,提供了一些特定状态的提示语
#import "State.h"
#import "SweetMaichine.h"
@implementation State
-(instancetype)initWithSweetMaichine:(SweetMaichine *)machine {
if (self = [super init]) {
_machine = machine;
}return self;
}
-(void)insertQuarter {
NSLog(@"没有糖果了,请下次光临!^v^");
}
-(void)enjectCuarter {
NSLog(@"你还没投币呢!真贪心...");
}
-(void)turnCrank {
NSLog(@"你转动了曲柄,没投钱,啥也没有...");
}
-(void)dispends {
NSLog(@"你需要先付钱才能得到糖果!");
}
@end
未投币状态
#import "NoQuarterState.h"
#import "SweetMaichine.h"
@implementation NoQuarterState
@synthesize machine = _machine;
-(instancetype)initWithSweetMaichine:(SweetMaichine *)machine {
if (self = [super initWithSweetMaichine:machine]) {
_machine = machine;
} return self;
}
-(void)insertQuarter {
_machine.state = _machine.hasQuarterState;
}
@end
已投币状态
#import "HasQuarterState.h"
#import "SweetMaichine.h"
@implementation HasQuarterState
@synthesize machine = _machine;
-(instancetype)initWithSweetMaichine:(SweetMaichine *)machine {
if (self = [super initWithSweetMaichine:machine]) {
_machine = machine;
}return self;
}
-(void)insertQuarter {
NSLog(@"已经投过钱了,再投可能被吞掉哦^v^");
}
-(void)enjectCuarter {
_machine.state = _machine.noQuarterState;
NSLog(@"请在退钞口接收您的退款,欢迎下次光临^v^");
}
-(void)turnCrank {
_machine.state = _machine.soldState;
}
-(void)dispends {
NSLog(@"你是不是搞错了?这是退糖果的时候?开发人员该打!");
}
@end
正在出货状态
#import "SoldState.h"
#import "SweetMaichine.h"
@implementation SoldState
@synthesize machine = _machine;
-(instancetype)initWithSweetMaichine:(SweetMaichine *)machine {
if (self = [super initWithSweetMaichine:machine]) {
_machine = machine;
}return self;
}
-(void)insertQuarter {
NSLog(@"光投币,不退糖果,也白投,不如等拿到糖果再试试吧!");
}
-(void)enjectCuarter {
NSLog(@"你的钱已经变成糖果了^v^,等等就能拿到v^v");
}
-(void)turnCrank {
NSLog(@"正在出糖果中,摇多少次都一样,等等吧^v^");
}
-(void)dispends {
if ([_machine hasSweet]) { [_machine popupSweet]; }
if ([_machine hasSweet]) {
_machine.state = _machine.noQuarterState;
}else {
_machine.state = _machine.soldOutState;
}
}
@end
卖光状态
#import "SoldOutState.h"
#import "SweetMaichine.h"
@implementation SoldOutState
@synthesize machine = _machine;
-(instancetype)initWithSweetMaichine:(SweetMaichine *)machine {
if (self = [super initWithSweetMaichine:machine]) {
_machine = machine;
}return self;
}
-(void)insertQuarter {
NSLog(@"当前糖果已经售光!您的现金会在退币处退出,欢迎下次光临!");
}
@end
售货机实现
#import "SweetMaichine.h"
@interface SweetMaichine ()
@property (nonatomic ,assign)NSInteger count;
@property (nonatomic ,strong)NoQuarterState * noQuarterState;
@property (nonatomic ,strong)HasQuarterState * hasQuarterState;
@property (nonatomic ,strong)SoldState * soldState;
@property (nonatomic ,strong)SoldOutState * soldOutState;
@end
@implementation SweetMaichine
-(instancetype)initWithSeets:(NSInteger)count {
if (self = [super init]) {
_count = count;
if (_count > 0) {
self.state = self.noQuarterState;
}else {
self.state = self.soldOutState;
}
} return self;
}
-(void)setState:(State *)state {
_state = state;
}
-(State *)noQuarterState {
if (!_noQuarterState) {
_noQuarterState = [[NoQuarterState alloc] initWithSweetMaichine:self];
}return _noQuarterState;
}
-(State *)hasQuarterState {
if(!_hasQuarterState) {
_hasQuarterState = [[HasQuarterState alloc] initWithSweetMaichine:self];
}return _hasQuarterState;
}
-(State *)soldState {
if (!_soldState) {
_soldState = [[SoldState alloc] initWithSweetMaichine:self];
}return _soldState;
}
-(State *)soldOutState {
if (!_soldOutState) {
_soldOutState = [[SoldOutState alloc] initWithSweetMaichine:self];
}return _soldOutState;
}
-(void)insertQuarter {
[self.state insertQuarter];
}
-(void)enjectCuarter {
[self.state enjectCuarter];
}
-(void)turnCrank {
[self.state turnCrank];
}
-(void)dispends {
[self.state dispends];
}
-(void)popupSweet {
_count --;
NSLog(@"你得到了一个糖果!");
}
-(BOOL)hasSweet {
if (_count > 0) {
return YES;
}
return NO;
}
@end
具体调用
#import <Foundation/Foundation.h>
#import "SweetMaichine.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
SweetMaichine * machine = [[SweetMaichine alloc] initWithSeets:1];
[machine insertQuarter];
[machine turnCrank];
[machine dispends];
}
return 0;
}
优点
1.封装了转换规则
2.枚举可能的状态,在枚举前需要确定具体状态
3.将所有与某个状态有关的逻辑放在一个类中,并且可以方便的增加新的状态,只需要改变状态就能改变行为。
4.允许状态与逻辑合为一体,而不是复杂的条件语句
5.可以多个对象持有一个状态,减少状态对象数。
缺点
1.增加了系统对象的个数
2.结构比较复杂,使用不当会导致代码结构混乱
3.开闭原则支持不太友好,如果要增加新的逻辑,可能会改动原有的代码逻辑