iOS開發-狀態模式

來源:互聯網
上載者:User

標籤:

狀態模式允許對象內部狀態改變時改變它的行為,對象看起來好像修改了它的類。狀態模式看起來和策略模式比較相像,策略模式是將可以互換的行為封裝起來,然後通過使用委託的方式,決定使用哪一個行為,狀態也是封裝行為,不同的是可以將行為委託到目前狀態。一個需要從外部設定,一個是內部通過狀態變更達到行為變成的目的。

基礎知識

狀態模式的UML類圖:

 

State封裝基本的狀態行為,我們通過Cotext上下文持有狀態子類的執行個體,外部發起請求,我們就可以委託狀態進行處理。地鐵裡面一般都有自動飲料售賣機,我們將所有的飲料都當做商品來看,我們如果需要買飲料需要兩步,投幣,取貨,如果沒有商品還可以退錢三種行為,關於自動售賣機的存在無錢狀態,有錢狀態,售賣中狀態,已售罄狀態四種狀態,稍微思考一下,可以看下面的具體實現。

設計實戰

狀態行為基類: 

@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):

@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

售賣機處於售賣狀態:

@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):

@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):

@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

測試:

    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也可以由狀態行為控制,比較靈活;

缺點: 狀態模式的使用必然會增加系統類別和對象的個數。狀態模式的結構與實現都較為複雜,如果使用不當將導致程式結構和代碼的混亂。

iOS開發-狀態模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.