State mode allows the object to change its behavior when its internal state changes, and the object looks as if it has modified its class. The state pattern looks similar to the policy pattern, which encapsulates the interchangeable behavior, and then decides which behavior to use by using the delegate, and the state is the encapsulation behavior, but the behavior can be delegated to the current state. One needs to be externally set, and the other is to internally change the state to achieve the purpose of the behavior.
Basic Knowledge
UML class diagram for State mode:
State encapsulates the basic status behavior, we can delegate the state to process by holding an instance of the state subclass through the Cotext context, and externally initiating the request. Subway inside generally have automatic drinks vending machine, we will all the beverage as a commodity, we need to buy a drink need two steps, coin, pick up, if there is no goods can also refund three kinds of behavior, about the existence of the vending machine no money state, rich state, the status of sale, sold out state four states, a little thought about , you can see the following specific implementation.
Design Combat
state behavior base class:
@protocol stateprotocol <NSObject> @optional-(void) Putmoney; @optional-(void) Ejectmoney; @optional-(void) Pressbutton, @optional-(void) distribute; @end @interface state:nsobject<stateprotocol> @end
The vending machine is in a state of no money (nomoneystate):
@protocol nomoneydelegate <nsobject>-(void) Setcurrentstate: (state *) currentstate;-(state *) gehasmoneystate;@ end//no money status @interface Nomoneystate:state@property (weak,nonatomic) id<nomoneydelegate> delegate; @end
@implementation nomoneystate-(void) putmoney{ NSLog (@ "Nomoneystate-putmoney: Serving Coins"); [Self.delegate setcurrentstate:[self.delegate gehasmoneystate];} -(void) ejectmoney{ NSLog (@ "Nomoneystate-ejectmoney: No money is invested, no refund");} -(void) pressbutton{ NSLog (@ "Nomoneystate-pressbutton: please coin first");} -(void) distribute{ NSLog (@ "Nomoneystate-pressbutton: please coin"); @end
The vending machine is in rich condition (hasmoneystate):
@protocol hasmoneydelegate <nsobject>-(void) Setcurrentstate: (state *) currentstate;-(state *) getnomoneystate;-(state *) getsoldstate; @end//Rich status @interface hasmoneystate:state@property (weak,nonatomic) id< Hasmoneydelegate> delegate; @end
@implementation hasmoneystate-(void) putmoney{ NSLog (@ "Hasmoneystate-putmoney: has invested money, temporarily does not support input");} -(void) ejectmoney{ NSLog (@ "Hasmoneystate-ejectmoney: Refund, re-set the vending machine as an unprecedented condition"); [Self.delegate setcurrentstate:[self.delegate getnomoneystate];} -(void) pressbutton{ NSLog (@ "Hasmoneystate-pressbutton: Button pressed, pickup"); [Self.delegate setcurrentstate:[self.delegate getsoldstate];} -(void) distribute{ NSLog (@ "Hasmoneystate-distribute: Unable to take out the product");} @end
The vending machine is in the selling state:
@protocol solddelegate <nsobject>-(void) Setcurrentstate: (state *) currentstate;-(void) realseproduct;-( Nsinteger) getcurrentcount;-(state *) getnomoneystate;-getsoldoutstate; @end//Sold status @interface soldstate: State@property (weak,nonatomic) id<solddelegate> delegate; @end
@implementation soldstate-(void) putmoney{ NSLog (@ "Soldstate-putmoney: Please wait for the sale of Goods");} -(void) ejectmoney{ NSLog (@ "Soldstate-putmoney: Please wait for the sale of goods, no refund"); -(void) pressbutton{ NSLog (@ "Soldstate-putmoney: Please re-coin after the item is removed");} -(void) distribute{ [Self.delegate realseproduct]; if ([Self.delegate Getcurrentcount]) { [self.delegate setcurrentstate:[self.delegate getnomoneystate]; } else{ [self.delegate setcurrentstate:[self.delegate getsoldoutstate]; }} @end
Sold out status (Soldoutstate):
@protocol soldoutdelegate <nsobject>-(void) Setcurrentstate: (state *) CurrentState; @end//Sold out status @interface Soldoutstate:state@property (weak,nonatomic) id<soldoutdelegate> delegate; @end
@implementation soldoutstate-(void) putmoney{ NSLog (@ "Soldoutstate-putmoney: Sold Out");} -(void) ejectmoney{ NSLog (@ "Soldoutstate-ejectmoney: no Refund");} -(void) pressbutton{ NSLog (@ "Soldoutstate-pressbutton: cannot be sold");} -(void) distribute{ NSLog (@ "Soldoutstate-distribute: unable to distribute");} @end
Vending Machine (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: Merchandise Sold"); if (self.productcount) {self.productcount-=1; }}-(state *) getsoldoutstate{return self.soldoutstate;} -(Nsinteger) getcurrentcount{return self.productcount;} @end
Test:
Salemachine *machine=[[salemachine alloc]initwithcount:1]; [Machine Putmoney]; [Machine Ejectmoney]; [Machine Putmoney]; [Machine Pressbutton]; Salemachine *next=[[salemachine alloc]initwithcount:1]; [Next Putmoney]; [Next Ejectmoney];
Test results:
Advantages and disadvantages of State mode:
Advantage: State mode allows an object to have different behavior based on internal state, delegate behavior to state object execution, state transformation can be controlled by context and state behavior, and is more flexible;
Disadvantages: the use of State mode will inevitably increase the number of system classes and objects. The structure and implementation of state patterns are more complex, and improper use will result in confusion of the program structure and code.
iOS Development-State mode