- Uses: Separate the algorithm from the object, so that the algorithm can be independent of the users who use it.
- Example: Travel, we can have several strategies to consider, can ride (object) bicycles, cars, do trains, airplanes. Each strategy can achieve the same results, but they use different resources. The basis for choosing a strategy (algorithm) is cost, time, tools and the convenience of each method.
-
structure
- Use policy patterns when the following situations exist (advantages)
Many related classes simply behave differently. Policies provide a way to configure a class with one behavior in multiple actions. That is, a system needs to dynamically select one of several algorithms.
Different variants of an algorithm need to be used. For example, you might define algorithms that reflect different spatial/temporal tradeoffs. When these variants are implemented as a class hierarchy of an algorithm, policy patterns can be used.
Algorithms use data that customers should not know. Policy patterns can be used to avoid exposing complex, algorithmically relevant data structures.
A class defines a variety of behaviors, and these behaviors occur in the form of multiple conditional statements in the operation of the class. Relevant conditional branches are moved into their respective policy classes to replace these conditional statements.
- shortcoming
1. The client must know all the policy classes and decide which one to use. That is to say, if a client wants to choose a suitable strategy, he must know how different these strategies are. At this point, you may have to expose specific implementation issues to your customers. Therefore, only when these different behavior variants are related to the customer's behavior, need to use the strategy pattern.
2. Communication overhead between Strategy and Context: Whether the algorithms implemented by ConcreteStrategy are simple or complex, they share the interfaces defined by Strategy. So it is likely that some ConcreteStrategy will not use all the information passed to them through this interface; a simple ConcreteStrategy may not use any of the information! This means that sometimes Context creates and initializes parameters that will never be used. If such a problem exists, a closer coupling between Strategy and Context will be required.
3. Policy patterns will result in many policy classes.
- iOS Application: Make an input box that only receives letters and numbers to verify login
When there are two or more input boxes in xib or sb, if it is called letterInput or numberInput, then it must be in view, or the controller will have the following code:
- (void)textFieldDidEndEditing:(UITextField *)textField{ if(textField == self.letterInput){ //Verification is the logic of letters, etc. }else if(textField == self.numberInput){ //Validation is the logic of numbers, etc. } }
Then, the problem is that if the input box is too long, there will be multiple conditional statements in the form, which is not conducive to expansion.
If the policy pattern is used:
- Then make a policy class InputTextField
// .h file @interface InputTextField : NSObject //Policy input verifies identity legitimacy - (BOOL)inputTextField:(UITextField *)textField; @end // .m file @implementation InputTextField - (BOOL)inputTextField:(UITextField *)textField{ return NO; } @end
- Context class: CustomTextField, inherits UITextField, and then interacts in view through CustomTextField in the controller
// .h file #import "InputTextField.h"//Aggregation Relations @interface CustomTextField : UITextField @property (nonatomic,strong)InputTextField *inputTextField;//Abstract policy class //Verification method - (BOOL)isOK; @end // .m file @implementation CustomTextField - (BOOL)isOK{ BOOL result = [self.inputTextField inputTextField:self]; if(!result){ NSLog(@"Illegal input"); } return result; } @end
- ConcreteStrategy Class: Integration Policy Class
LetterInput:
@implementation LetterInput - (BOOL)inputTextField:(UITextField *)textField{ // Verify that LetterInput is legal } @end
NumberInput:
@implementation NumberInput - (BOOL)inputTextField:(UITextField *)textField{ // Verify that NumberInput is legal } @end
- Call:
The input box becomes CustomTextField
@property (weak, nonatomic) IBOutlet CustomTextField *letterInput;//Alphabetic input @property (weak, nonatomic) IBOutlet CustomTextField *numberInput;//Digital input
Initialize the actual policy class
//Initialization self.letterInput.inputTextField = [LetterInput new]; self.numberInput.inputTextField = [NumberInput new];
Verify that the input box is legitimate
- (void)textFieldDidEndEditing:(UITextField *)textField{ if ([textField isKindOfClass:[CustomTextField class]]) { [(CustomTextField *)textField isOK]; } }
From this we can see that:
1. Conditional judgment is omitted and their logic is distributed in their strategies.
2. Extensibility. If additional validation is needed later, add the policy method - (BOOL) inputAnotherTextField:(UITextField*) textField; (BOOL) is AnotherOK; (BOOL) is added to the Context class; and then add logic to the corresponding ConcreteStrategy class.