preface
I attended the strategy pattern seminar this Friday. The purpose of this article is to summarize and share this pattern, hoping to be helpful to students who need to learn this design pattern. This paper is divided into two parts. The first part is the summary of the basic knowledge of strategy model; The second part is a simple example of the sharing policy pattern.1, Strategy mode summary
1. Model intention
Define a series of algorithms, encapsulate them one by one, and make them replaceable. This pattern allows the algorithm to vary independently of the customers using it.2. Participants
Strategy
– define the common interface of all algorithms. context uses this interface to call an algorithm defined by a concreteStrategy;
Concrete strategy
– implement a specific algorithm with Strategy interface;
Context
– configure with a ConcreteStrategy object;
– maintain a reference to the Strategy object;
– an interface can be defined to allow Strategy to access its data;
3. Structure, cooperation, applicability and effect
Structure diagram:1. Strategy and Context interact to implement the selected algorithm. When the algorithm is called, Context can pass all the data required by the algorithm to the strategy. Alternatively, Context can pass itself as a parameter to the strategy operation. This allows strategy to call back Context when necessary;
2. Context forwards the requests of its customers to its Strategy. Customers usually create and pass a ConcreteStrategy object to the context; In this way, the customer only interacts with context. There are usually a series of ConcreteStrategy classes for customers to choose from. Applicability:
1. Many related classes simply behave differently. Policy provides a way to configure a class with one of several behaviors.
2. Different variants of an algorithm need to be used. For example, you may define some algorithms that reflect different space / time tradeoffs. When these variants are implemented as a class hierarchy of an algorithm, the policy pattern can be used.
3. The algorithm uses data that customers should not know. Policy patterns can be used to avoid exposing complex algorithm related data structures.
4. A class defines multiple behaviors, and these behaviors appear in the form of multiple conditional statements in the operation of this class. Move the relevant conditional branches into their respective Strategy classes to replace these conditional statements.
effect:
1. Related algorithm series.
The Strategy class hierarchy defines a series of reusable algorithms or behaviors for Context. inherit
It is helpful to analyze the common functions in these algorithms
Inheritance provides another way to support multiple algorithms or behaviors. You can give birth directly
Into a subclass of Context class, so as to give it different behavior. However, this will hard code the behavior into the Context instead of
The implementation of the algorithm is mixed with the implementation of the Context, which makes the Context difficult to understand, maintain and expand, and
The algorithm cannot be changed dynamically. Finally, you get a bunch of related classes. The only difference between them is the algorithm they use
Or behavior. Encapsulating the algorithm in a separate Strategy class allows you to change it independently of its Context, making it easy to switch
Easy to understand and expand.
3. Some conditional statements are eliminated.
The Strategy pattern provides an alternative to selecting the desired behavior with conditional statements
Choose. When different behaviors are stacked in a class, it is difficult to avoid using conditional statements to select the appropriate behavior. Encapsulate behavior
These conditional statements are eliminated in separate Strategy classes.
The Strategy pattern can provide different implementations of the same behavior. Customers can choose according to different time / space
Trade offs require choices from different strategies.
A potential disadvantage of this model is that if a customer wants to choose an appropriate Strategy, he must know how these strategies are different. At this point, you may have to expose specific implementation problems to customers. Therefore, the Strategy pattern needs to be used only when these different behavior variants relate to customer related behavior.
6. Communication overhead between Strategy and Context.Whether the algorithm implemented by each concrete strategy is simple or complex
They all share the interface defined by Strategy. Therefore, it is likely that some concretestrategies will not use all of them
Information transmitted to them by multiple interfaces; Simple ConcreteStrategy may not use any of the information! This means that sometimes Context creates and initializes parameters that will never be used. If there is such a problem, there will be a need for closer coupling between Strategy and Context.
2, Simple example of policy pattern
1. Use case description
The main purpose of the strategy is to define a series of algorithms, encapsulate them one by one, and make them replaceable. Therefore, this mode mainly uses the scenario algorithm. As we all know, the traversal of binary tree is divided into pre order traversal, middle order traversal and post order traversal. We encapsulate these three algorithms so that when traversing the tree, we can switch different traversal algorithms as needed. This is a typical application scenario of policy mode. Preorder traversal: root node + left subtree + right subtreeWhen traversing the left subtree and the right subtree, you still access the root node first, then traverse the left subtree, and finally traverse the right subtree.
Middle order traversal: left subtree + root node + right subtreeWhen traversing the left and right subtrees, we still traverse the left subtree, then the root node, and then the right subtree.
Post order traversal: left subtree + right subtree + root nodeWhen traversing the left and right subtrees, the left subtree is traversed first, the right subtree is traversed, and then the root node is accessed.
2. Sample code
typedef struct tag_tree_node { //Node data char data; //Left child node pointer struct tag_tree_node* left_child; //Right child node pointer struct tag_tree_node* right_child; }tree_node_t; class show_tree_base_t { public: virtual void show_tree(tree_node_t* root) = 0; void visit(tree_node_t* root); }; void show_tree_base_t::visit(tree_node_t *node){ } class show_tree_pre_t : public show_tree_base_t{ public: virtual void show_tree(tree_node_t* root); }; void show_tree_pre_t::show_tree(tree_node_t *root){ visit(root); this->show_tree(root->left_child); this->show_tree(root->right_child); } class show_tree_in_t : public show_tree_base_t{ public: virtual void show_tree(tree_node_t* root); }; void show_tree_in_t::show_tree(tree_node_t *root){ this->show_tree(root->left_child); visit(root); this->show_tree(root->right_child); } class show_tree_post_t : public show_tree_base_t{ public: virtual void show_tree(tree_node_t* root); }; void show_tree_post_t::show_tree(tree_node_t *root){ this->show_tree(root->left_child); this->show_tree(root->right_child); visit(root); } tree_node_t* create_tree(){ } void delete_tree(tree_node_t* root) { } class context_t { public: void set_show_strategy(show_tree_base_t* obj) { m_show_tree_obj = obj; } void show(tree_node_t *root) { if (m_show_tree_obj != nullptr && root != nullptr) { m_show_tree_obj->show_tree(root); } } private: show_tree_base_t* m_show_tree_obj = nullptr; }; int main(int argc, char *argv[]) { show_tree_pre_t* pre = new show_tree_pre_t; show_tree_in_t* in = new show_tree_in_t; show_tree_post_t* post = new show_tree_post_t; context_t* ctx = new context_t; tree_node_t *root = create_tree(); //Preorder traversal ctx->set_show_strategy(pre); ctx->show(root); //Medium order traversal ctx->set_show_strategy(in); ctx->show(root); //Postorder traversal ctx->set_show_strategy(post); ctx->show(root); delete pre; delete in; delete post; delete_tree(root); return 0; }