iOS開發-狀態模式

狀態模式容許對象內部狀態改變時改變它的行爲,對象看起來好像修改了它的類。狀態模式看起來和策略模式比較相像,策略模式是將能夠互換的行爲封裝起來,而後經過使用委託的方式,決定使用哪個行爲,狀態也是封裝行爲,不一樣的是能夠將行爲委託到當前狀態。一個須要從外部設置,一個是內部經過狀態變動達到行爲變成的目的。測試

基礎知識

狀態模式的UML類圖:atom

 

State封裝基本的狀態行爲,咱們經過Cotext上下文持有狀態子類的實例,外部發起請求,咱們就能夠委託狀態進行處理。地鐵裏面通常都有自動飲料售賣機,咱們將全部的飲料都當作商品來看,咱們若是須要買飲料須要兩步,投幣,取貨,若是沒有商品還能夠退錢三種行爲,關於自動售賣機的存在無錢狀態,有錢狀態,售賣中狀態,已售罄狀態四種狀態,稍微思考一下,能夠看下面的具體實現。spa

設計實戰

狀態行爲基類: 設計

@protocol StateProtocol <NSObject>

@optional
-(void)putMoney;
@optional
-(void)ejectMoney;
@optional
-(void)pressButton;
@optional
-(void)distribute;

@end

@interface State : NSObject<StateProtocol>

@end

 

售賣機處於無錢狀態(NoMoneyState):對象

@protocol NoMoneyDelegate <NSObject>

-(void)setCurrentState:(State *)currentState;

-(State *)geHasMoneyState;

@end

//沒錢狀態
@interface NoMoneyState : State

@property (weak,nonatomic) id<NoMoneyDelegate>  delegate;

@end
@implementation NoMoneyState

-(void)putMoney{
    NSLog(@"NoMoneyState-putMoney:投放錢幣");
    [self.delegate setCurrentState:[self.delegate geHasMoneyState]];
}

-(void)ejectMoney{
     NSLog(@"NoMoneyState-ejectMoney:沒有投入錢幣,沒法退錢");
}

-(void)pressButton{
    NSLog(@"NoMoneyState-pressButton:請先投幣");
}

-(void)distribute{
     NSLog(@"NoMoneyState-pressButton:請投幣");
}

@end

售賣機處於有錢狀態(HasMoneyState):blog

@protocol  HasMoneyDelegate <NSObject>

-(void)setCurrentState:(State *)currentState;

-(State *)getNoMoneyState;

-(State *)getSoldState;

@end
//有錢狀態
@interface HasMoneyState : State

@property (weak,nonatomic) id<HasMoneyDelegate> delegate;

@end
@implementation HasMoneyState

-(void)putMoney{
    NSLog(@"HasMoneyState-putMoney:已經投入了錢,暫不支持投入");
}

-(void)ejectMoney{
    NSLog(@"HasMoneyState-ejectMoney:退錢,從新設置售賣機爲無前狀態");
    [self.delegate setCurrentState:[self.delegate getNoMoneyState]];
}

-(void)pressButton{
   NSLog(@"HasMoneyState-pressButton:按鈕按下,取貨");
   [self.delegate setCurrentState:[self.delegate getSoldState]];
}

-(void)distribute{
  NSLog(@"HasMoneyState-distribute:沒法進行取出商品");
}

@end

售賣機處於售賣狀態:get

@protocol  SoldDelegate <NSObject>

-(void)setCurrentState:(State *)currentState;

-(void)realseProduct;

-(NSInteger)getCurrentCount;

-(State *)getNoMoneyState;

-(State *)getSoldOutState;

@end
//售出狀態
@interface SoldState : State

@property (weak,nonatomic) id<SoldDelegate> delegate;

@end
@implementation SoldState

-(void)putMoney{
    NSLog(@"SoldState-putMoney:請稍後,正在進行商品出售");
}

-(void)ejectMoney{
     NSLog(@"SoldState-putMoney:請稍後,正在進行商品出售,沒法退錢");
}

-(void)pressButton{
    NSLog(@"SoldState-putMoney:請在取出物品以後從新投幣");
}

-(void)distribute{
    [self.delegate realseProduct];
    if ([self.delegate getCurrentCount]) {
        [self.delegate setCurrentState:[self.delegate getNoMoneyState]];
    }else{
        [self.delegate setCurrentState:[self.delegate getSoldOutState]];
    }
}

@end

售罄狀態(SoldOutState):it

@protocol  SoldOutDelegate <NSObject>

-(void)setCurrentState:(State *)currentState;

@end
//售罄狀態
@interface SoldOutState : State

@property (weak,nonatomic) id<SoldOutDelegate>  delegate;

@end
@implementation SoldOutState

-(void)putMoney{
    NSLog(@"SoldOutState-PutMoney:已售罄");
}

-(void)ejectMoney{
    NSLog(@"SoldOutState-ejectMoney:沒法退錢");
}

-(void)pressButton{
    NSLog(@"SoldOutState-pressButton:沒法售出");
}

-(void)distribute{
    NSLog(@"SoldOutState-distribute:沒法分發");
}

@end

售賣機(SaleMachine):io

@interface SaleMachine : NSObject<NoMoneyDelegate,HasMoneyDelegate,SoldOutDelegate,SoldDelegate>

@property  (strong,nonatomic) NoMoneyState  *noMoneyState;
@property  (strong,nonatomic) HasMoneyState *hasMoneyState;
@property  (strong,nonatomic) SoldOutState  *soldOutState;
@property  (strong,nonatomic) SoldState     *soldState;

-(instancetype)initWithCount:(NSInteger)count;

-(void)setCurrentState:(State *)currentState;

-(void)putMoney;
-(void)ejectMoney;
-(void)pressButton;

@end
@interface SaleMachine()

@property (strong,nonatomic)  State *state;
@property (assign,nonatomic)  NSInteger  productCount;

@end

@implementation SaleMachine

-(instancetype)initWithCount:(NSInteger)count{
    self=[super init];
    if (self) {
        self.noMoneyState=[[NoMoneyState alloc]init];
        self.noMoneyState.delegate=self;
        self.hasMoneyState=[[HasMoneyState alloc]init];
        self.hasMoneyState.delegate=self;
        self.soldState=[[SoldState alloc]init];
        self.soldState.delegate=self;
        self.soldOutState=[[SoldOutState alloc]init];
        self.soldOutState.delegate=self;
        self.productCount=count;
        if (count) {
            self.state=self.noMoneyState;
        }
    }
    return self;
}

-(void)putMoney{
    [self.state putMoney];
}

-(void)ejectMoney{
    [self.state ejectMoney];
}

-(void)pressButton{
    [self.state pressButton];
    [self.state distribute];
}

-(void)setCurrentState:(State *)currentState{
    self.state=currentState;
}
#pragma mark - NoMoenyDelegate
-(State *)geHasMoneyState{
    return self.hasMoneyState;
}

#pragma mark - HasMoneyDelegate
-(State *)getNoMoneyState{
    return self.noMoneyState;
}

-(State *)getSoldState{
    return self.soldState;
}
#pragma mark - SoldDelegate
-(void)realseProduct{
    NSLog(@"SoldDelegate-realseProduct:商品售出");
    if (self.productCount) {
        self.productCount-=1;
    }
}

-(State *)getSoldOutState{
    return self.soldOutState;
}

-(NSInteger)getCurrentCount{
    return self.productCount;
}

@end

測試:class

    SaleMachine *machine=[[SaleMachine alloc]initWithCount:1];
    [machine putMoney];
    [machine ejectMoney];
    
    [machine putMoney];
    [machine pressButton];
    
    SaleMachine *next=[[SaleMachine alloc]initWithCount:1];
    [next putMoney];
    [next ejectMoney];

測試效果:

  

狀態模式的優缺點:

優勢:狀態模式容許一個對象基於內部狀態有不一樣的行爲,將行爲委託給狀態對象執行,狀態轉化能夠由Context也能夠由狀態行爲控制,比較靈活;

缺點: 狀態模式的使用必然會增長系統類和對象的個數。狀態模式的結構與實現都較爲複雜,若是使用不當將致使程序結構和代碼的混亂。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息