1. Overview
In the software development process, the application may make different processing depending on the situation. The most straightforward solution is to take all of these possible scenarios into account. Then use the If ... ellse statement to do the state judgment to handle the different situations. But the judgment of complex state appears to be "powerless". As you add new states or modify a body (if else (or switch case) statements increase or modify), it can cause significant changes, and the readability and extensibility of the program becomes weak. Maintenance can also be very troublesome. Then I'll consider the pattern of only modifying my own state.
Example 1: button to control the state of an elevator, an elevator open, close, stop, run. Each state change, it is possible to update the processing according to other states. For example, if you open the door, you cannot open the door at the time of operation, but only when the elevator is settled.
Example 2: We call a cell phone, there may be these kinds of situations: User boot, user shutdown, users owe downtime, users, such as consumer. So when we dial this number: The system must determine whether the user is on the boot and not busy state, or shutdown, due to the status of the fee. But in either case, we should give the corresponding processing operation.
2. The question
How does an object behave differently in each state?
3. The solution
State mode: Allows an object to change its behavior when its internal state changes. The object appears to modify its class.
In many cases, the behavior of an object depends on one or more dynamically changing properties, called states, where the object is called a stateful (stateful) object, and the object state is taken out of a well-defined series of values. When an object interacts with an external event, its internal state changes and the behavior of the system changes.
4. Example
first, the class structure diagram of this example is given.
The above class structure diagram is not complex, the first is to abstract a state of the parent class, through the work class on the point of time settings to switch different states.
Logical structure is not complex, or give a simple code, we can slowly experience.
Note: All of the code in this article is compiled in an arc environment.
Work class Interface
Copy Code code as follows:
#import <Foundation/Foundation.h>
@class State;
@interface work:nsobject{
State *current;
}
@property double Hour;
@property BOOL taskfinished;
-(void) SetState: (state*) s;
-(void) Writeprogram;
@end
Work class implementation
Copy Code code as follows:
#import "Work.h"
#import "State.h"
#import "ForenoonState.h"
@implementation Work
@synthesize Hour =_hour;
@synthesize taskfinished =_taskfinished;
-(ID) init{
if (self = = [Superinit]) {
current= [[Forenoonstate alloc]init];
}
return self;
}
-(void) SetState: (state *) s{
current = s;
}
-(void) writeprogram{
[Current writeprogram:self];
}
@end
State Class Interface
Copy Code code as follows:
#import <Foundation/Foundation.h>
@class Work;
@interface State:nsobject
-(void) Writeprogram: (work*) W;
@end
State Class implementation
Copy Code code as follows:
#import "State.h"
#import "Work.h"
@implementation State
-(void) Writeprogram: (Work *) w{
NSLog (@ "Current time:%f point to go home from work", [w Hour]);
}
@end
Forenoonstate class Interface
Copy Code code as follows:
#import "State.h"
@interface Forenoonstate:state
@end
Forenoonstate class implementation
Copy Code code as follows:
#import "ForenoonState.h"
#import "Work.h"
#import "NoonState.h"
@implementation Forenoonstate
-(void) Writeprogram: (Work *) w{
if ([w Hour] < 12) {
NSLog (@ "Current time:%f point morning work, Spirit Hundredfold", [w Hour]);
}
else {
[w setstate:[noonstate New]];
[w Writeprogram];
}
}
@end
Noonstate class Interface
Copy Code code as follows:
#import "State.h"
@interface Noonstate:state
@end
Noonstate class implementation
Copy Code code as follows:
#import "NoonState.h"
#import "Work.h"
#import "AfternoonState.h"
@implementation Noonstate
-(void) Writeprogram: (Work *) w{
if ([w Hour] <13)
NSLog (@ "Current time:%f point hungry, lunch, sleepy, Siesta", [w Hour]);
else {
[w setstate:[[afternoonstate Alloc]init]];
[w Writeprogram];
}
}
@end
Afternoonstate class Interface
Copy Code code as follows:
#import "State.h"
@interface Afternoonstate:state
@end
Afternoonstate class implementation
Copy Code code as follows:
#import "AfternoonState.h"
#import "Work.h"
#import "EveningState.h"
@implementation Afternoonstate
-(void) Writeprogram: (Work *) w{
if ([w Hour] <17) {
NSLog (@ "Current time:%f point afternoon status is not bad, continue to work", [w Hour]);
}
else {
[w setstate:[[eveningstate Alloc]init]];
[w Writeprogram];
}
}
@end
Eveningstate class Interface
Copy Code code as follows:
#import "State.h"
@interface Eveningstate:state
@end
Eveningstate class implementation
Copy Code code as follows:
#import "EveningState.h"
#import "Work.h"
#import "RestState.h"
#import "SleepingState.h"
@implementation Eveningstate
-(void) Writeprogram: (Work *) w{
if ([w taskfinished]) {
[w setstate:[[reststate Alloc]init]];
[w Writeprogram];
}
else {
if ([w Hour] <21)
NSLog (@ "Current time:%f point overtime Oh, exhausted extreme", [w Hour]);
else {
[w setstate:[[sleepingstate Alloc]init]];
[w Writeprogram];
}
}
}
@end
Sleepingstate class Interface
Copy Code code as follows:
#import "State.h"
@interface Sleepingstate:state
@end
Sleepingstate class implementation
Copy Code code as follows:
#import "SleepingState.h"
#import "Work.h"
@implementation Sleepingstate
-(void) Writeprogram: (Work *) w{
NSLog (@ "Current time:%f point is dead, asleep", [w Hour]);
}
@end
Reststate class Interface
Copy Code code as follows:
#import "RestState.h"
#import "Work.h"
@implementation Reststate
-(void) Writeprogram: (Work *) w{
NSLog (@ "Current time:%f point to go home from work", [w Hour]);
}
@end
Main method call
Copy Code code as follows:
#import <Foundation/Foundation.h>
#import "Work.h"
int main (int argc,const char *argv[])
{
@autoreleasepool {
Work *emergencyprojects = [[Work alloc]init];
[Emergencyprojects Sethour:9];
[Emergencyprojects Writeprogram];
[Emergencyprojects Sethour:10];
[Emergencyprojects Writeprogram];
[Emergencyprojects Sethour:12];
[Emergencyprojects Writeprogram];
[Emergencyprojects sethour:13];
[Emergencyprojects Writeprogram];
[Emergencyprojects sethour:14];
[Emergencyprojects Writeprogram];
[Emergencyprojects sethour:17];
[Emergencyprojects Writeprogram];
[Emergencyprojects Settaskfinished:no];
[Emergencyprojects sethour:19];
[Emergencyprojects Writeprogram];
[Emergencyprojects sethour:22];
[Emergencyprojects Writeprogram];
}
return 0;
}
The above is a simple code that is implemented in the Objective C language.
From this example, you can see that the state pattern reduces dependencies by distributing the various state transitions logically between the states ' subclasses. When an object's behavior depends on its state, and it must change its behavior according to its state at run time, you can consider using the state mode.
5. Applicability
The state pattern can be used in either of the following situations:
1 The behavior of an object depends on its state, and it must change its behavior according to the state at run time.
2) • Code contains a large number of conditional statements related to the state of the object: an operation with a large number of branching conditions (if else (or switch case) statements, and those branches depend on the state of the object. This state is usually represented by one or more enumerated constants. Typically, there are multiple operations that contain this same conditional structure. The state pattern places each conditional branch into a separate class. This allows you to use the object's state as an object based on the object itself, which can be changed independently of other objects.
6. Structure
7. Composition of the pattern
Environment Class (context): Defines the interfaces that customers are interested in. Maintains an instance of a concretestate subclass that defines the current state.
Abstract Status Class (state): Defines an interface to encapsulate the behavior associated with a particular state of the context.
Specific State Class (Concretestate): Each subclass implements a behavior associated with a state of the context.
8. Effect
The state pattern has some of the following effects:
Advantages of State mode:
1 It will localize the behavior associated with a particular state and separate the behavior of the different states: the state pattern puts all the behaviors associated with a particular state into an object. Because all state-related code exists in a particular state subclass, it is easy to add new states and transformations by defining new subclasses. Another approach is to use data values to define the internal state and have the context operation explicitly examine the data. This would, however, make the implementation of the entire context look like a conditional if Else statement or switch case statement that looks very similar. Adding a new state may require several operations to be changed, which makes maintenance complex. The state pattern avoids this problem, but it may introduce another problem, because the pattern distributes the behavior of different states in more than one class. This increases the number of subclasses, which is less compact than the implementation of a single class. However, if you have many states, such distributions are actually better, otherwise you need to use a large conditional statement. As with long processes, large conditional statements are unwelcome. They form a large block and make the code less clear, which makes them difficult to modify and extend. The state pattern provides a better way to organize code that is related to a particular status. The logic that determines the state transition is not in a single block I f or S w i t c H statement, but in between the States subclass. By encapsulating each state transition and action into a class, the focus is raised from the execution state to the state of the entire object. This makes the code more structured and makes its intentions clearer.
2 It makes the state transition explicit: When an object defines the current state only as an internal data value, its state is expressed only as an assignment to some variables, which is not clear enough. The introduction of independent objects for different states makes the transformation more explicit. Furthermore, the State object guarantees that no internal state inconsistency occurs in the context, because the transition is atomic from the context point of view-just rebind a variable (that is the state object variable of the contexts) without assigning a value to multiple variables
3 The state object can be shared if there are no instance variables for the states object-that is, they represent completely encoded by their type-then the context objects can share a single one. When states are shared in this way, they must be of no internal state, only lightweight objects of behavior.
Disadvantages of State mode:
1 The use of State mode will inevitably increase the number of system classes and objects.
2 The structure and implementation of State mode are complex, if improper use will lead to the confusion of program structure and code.