0. Ma Xian inspirational
Human beings are great because of their dreams. Action is the beginning of dreams.
1. General
First look at the pictures below. There are many travel modes for us to travel. We can ride a bike, take a car, take a train and take a plane.
As a program ape, you need to choose a development tool for development. Of course, there are many tools for code development. You can choose Idea for development, eclipse for development, or some other development tools.
definition:
This pattern defines a series of algorithms and encapsulates each algorithm so that they can be replaced with each other, and the change of the algorithm will not affect the customers using the algorithm. The policy pattern belongs to the object behavior pattern. It separates the responsibility of using the algorithm from the implementation of the algorithm by encapsulating the algorithm, and delegates it to different objects to manage these algorithms.
2. Structure
The main roles of the policy mode are as follows:
- Abstract Strategy class: This is an abstract role, usually implemented by an interface or abstract class. This role gives the interfaces required for all specific policy classes.
- Concrete Strategy class: implements the interface of abstract policy definition and provides specific algorithm implementation or behavior.
- Context class: holds a reference to a policy class, which is finally called to the client.
3. Case realization
Promotion activities
A department store's annual promotion. Different promotional activities are launched for different festivals (Spring Festival, Mid Autumn Festival and Christmas), and the promoters show the promotional activities to customers. Class diagram is as follows:
The code is as follows:
Define the common interface for all promotional activities of the department store
public interface Strategy { void show(); }
Define Concrete Strategy: specific promotional activities for each festival
//Promotional activities for the Spring Festival A public class StrategyA implements Strategy { public void show() { System.out.println("Buy 1 Get 1 FREE"); } } //Promotional activities for the Mid Autumn Festival B public class StrategyB implements Strategy { public void show() { System.out.println("50 yuan less than 200 yuan"); } } //Promotion for Christmas C public class StrategyC implements Strategy { public void show() { System.out.println("Over 1000 yuan plus 1 yuan for any commodity below 200 yuan"); } }
Define environment role (Context): used to connect the Context, that is, sell promotional activities to customers, which can be understood as salesperson here
public class SalesMan { //Holds a reference to an abstract policy role private Strategy strategy; public SalesMan(Strategy strategy) { this.strategy = strategy; } //Show promotions to customers public void salesManShow(){ strategy.show(); } }
4. Advantages and disadvantages
1. Advantages:
-
Policy classes can be switched freely
Since the policy classes all implement the same interface, they can switch freely.
-
Easy to expand
To add a new policy, you only need to add a specific policy class, basically do not need to change the original code, and comply with the "opening and closing principle"“
-
Avoid using multiple conditional selection statements (if else) and fully reflect the idea of object-oriented design.
2. Disadvantages:
- The client must know all policy classes and decide which policy class to use.
- The policy pattern will result in many policy classes. You can reduce the number of objects to a certain extent by using the meta pattern.
5. Usage scenario
- When a system needs to dynamically select one of several algorithms, each algorithm can be encapsulated into a policy class.
- A class defines multiple behaviors, and these behaviors appear in the form of multiple conditional statements in the operation of this class. Each conditional branch can be moved into their respective policy class to replace these conditional statements.
- Each algorithm in the system is completely independent of each other, and it is required to hide the implementation details of the specific algorithm from the customer.
- When the system requires that the customer using the algorithm should not know the data it operates, the policy pattern can be used to hide the data structure related to the algorithm.
- Multiple classes only have different behaviors. You can use the policy mode to dynamically select the specific behavior to be executed at run time.
6.JDK source code analysis
Policy pattern in Comparator. There is a sort() method in the Arrays class, as follows:
public class Arrays{ public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } } }
Arrays is an environment role class. This sort method can pass a new policy to let arrays sort according to this policy, such as the following test class.
public class demo { public static void main(String[] args) { Integer[] data = {12, 2, 3, 2, 4, 5, 1}; // Implement descending sort Arrays.sort(data, new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { return o2 - o1; } }); System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1] } }
Here, when we call the sort method of Arrays, the second parameter passes the sub implementation class object of the Comparator interface. Therefore, Comparator acts as an abstract policy role, and the specific sub implementation class acts as a specific policy role. Environment role class (Arrays) It should be called with a reference to the abstract policy. So, does the sort method of the Arrays class use the compare() method in the Comparator subclass? Let's continue to check the sort() method of the TimSort class. The code is as follows:
class TimSort<T> { static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c, T[] work, int workBase, int workLen) { assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length; int nRemaining = hi - lo; if (nRemaining < 2) return; // Arrays of size 0 and 1 are always sorted // If array is small, do a "mini-TimSort" with no merges if (nRemaining < MIN_MERGE) { int initRunLen = countRunAndMakeAscending(a, lo, hi, c); binarySort(a, lo, hi, lo + initRunLen, c); return; } ... } private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) { assert lo < hi; int runHi = lo + 1; if (runHi == hi) return 1; // Find end of run, and reverse range if descending if (c.compare(a[runHi++], a[lo]) < 0) { // Descending while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0) runHi++; reverseRange(a, lo, runHi); } else { // Ascending while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0) runHi++; } return runHi - lo; } }
The above code will eventually run to the countrunandmakescreening() method. We can see that only the compare method is used, so when calling the Arrays.sort method, only the class object of the specific compare rewriting method is passed. This is also a method that must be implemented by subclasses in the Comparator interface.
This blog comes from the summary of dark horse programmer's video tutorial and the arrangement of notes. It is only for learning and communication. It should not be used for commercial purposes. If there is infringement, please contact the blogger to delete it. Blogger QQ: 194760901