Writing in the front

  • Take notes on learning design patterns
  • Improve the flexible use of design patterns

Learning to address

www.bilibili.com/video/BV1G4…

www.bilibili.com/video/BV1Np…

Refer to the article

C.biancheng.net/view/1317.h…

Program source code

Gitee.com/zhuang-kang…

26. Strategic mode

26.1 Definition and characteristics of the policy pattern

Definition of a Strategy pattern: ** This pattern defines a series of algorithms and encapsulates each algorithm so that they are interchangeable and changes to the algorithm do not affect the customers using the algorithm. The ** strategy pattern belongs to the object behavior pattern. It encapsulates the algorithm, separates the responsibility of using the algorithm from the implementation of the algorithm, and assigns different objects to manage these algorithms.

The main advantages of the policy pattern are as follows.

  1. Multi-conditional statements are difficult to maintain, and using policy patterns can avoid multi-conditional statements, such as if… Else statement, switch… A case statement.
  2. The policy pattern provides a family of algorithms that can be reused, and inheritance can be used appropriately to move the common code of the algorithm family into the parent class to avoid duplicate code.
  3. The policy pattern can provide different implementations of the same behavior, and customers can choose different ones based on different time or space requirements.
  4. The policy pattern provides perfect support for the open closed principle, allowing for the flexibility of adding new algorithms without modifying the original code.
  5. The policy pattern separates the use of the algorithm into the environment class and the implementation of the algorithm into the concrete policy class.

Its main disadvantages are as follows.

  1. The client must understand the differences between all the policy algorithms in order to select the right algorithm class at the right time.
  2. The policy mode creates many policy classes, which increases the maintenance difficulty.

26.2 Structure and implementation of policy pattern

26.2.1 Structure of the policy pattern

  1. Abstract Strategy class: Defines a common interface that is implemented in different ways by different algorithms, and is used by environment actors to invoke different algorithms, typically implemented using interfaces or abstract classes.
  2. Concrete Strategy class: Interfaces that implement abstract policy definitions and provide Concrete algorithm implementations.
  3. Context class: Holds a reference to a policy class that is ultimately called by the client.

26.2.2 Code implementation

Different promotions for different festivals

Relationship between the class diagram

Strategy

package com.zhuang.strategy;

/ * * *@Classname Strategy
 * @DescriptionDefine the common interface *@Date2021/3/31 days *@Created by dell
 */

public interface Strategy {
    void show(a);
}
Copy the code

StrategyA

package com.zhuang.strategy;

/ * * *@Classname StrategyA
 * @DescriptionDefine specific strategy roles for specific promotions for each holiday *@Date2021/3/31 days *@Created by dell
 */

public class StrategyA implements Strategy {

    @Override
    public void show(a) {
        System.out.println("A promotion buy one get one free"); }}Copy the code

StrategyB

package com.zhuang.strategy;

/ * * *@Classname StrategyB
 * @DescriptionDefine specific strategy roles for specific promotions for each holiday *@Date2021/3/31 hold *@Created by dell
 */

public class StrategyB implements Strategy {

    @Override
    public void show(a) {
        System.out.println("B promotion 100 minus 20"); }}Copy the code

StrategyC

package com.zhuang.strategy;

/ * * *@Classname StrategyC
 * @DescriptionDefine specific strategy roles for specific promotions for each holiday *@Date2021/3/31 hold *@Created by dell
 */

public class StrategyC implements Strategy {

    @Override
    public void show(a) {
        System.out.println("C promotion over 500 yuan can be exchanged for small gifts"); }}Copy the code

SalesMan

package com.zhuang.strategy;

/ * * *@Classname SalesMan
 * @DescriptionDefine environmental roles to be used to connect the context to sell promotions to customers *@Date2021/3/31 * descend@Created by dell
 */

public class SalesMan {

    // Holds a reference to the abstract policy role
    private Strategy strategy;

    public SalesMan(Strategy strategy) {
        this.strategy = strategy;
    }

    public Strategy getStrategy(a) {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    // Display promotions
    public void salesManShow(a) { strategy.show(); }}Copy the code

Client

package com.zhuang.strategy;

/ * * *@Classname Client
 * @DescriptionPolicy pattern test classes *@Date2021/3/31 and *@Created by dell
 */

public class Client {
    public static void main(String[] args) {
        SalesMan salesMan = new SalesMan(new StrategyA());
        / / the children's day
        salesMan.salesManShow();

        System.out.println("= = = = = = = = = = = = = = = = = = = = = = =");
        / / labor day
        salesMan.setStrategy(new StrategyB());
        salesMan.salesManShow();

        System.out.println("= = = = = = = = = = = = = = = = = = = = = = =");
        / / the Dragon Boat Festival
        salesMan.setStrategy(newStrategyC()); salesMan.salesManShow(); }}Copy the code

26.3 Application Scenarios of policy Mode

  • When a system needs to dynamically select one of several algorithms, each algorithm can be encapsulated in a policy class.
  • A class defines multiple behaviors that occur as conditional statements in the actions of that class, and each conditional branch can be moved into its own policy class to replace those conditional statements.
  • Each algorithm in the system is completely independent of each other, and the implementation details of the specific algorithm are required to be hidden from customers.
  • Policy patterns can be used to hide data structures associated with algorithms when the system requires that customers using algorithms should not know the data they operate on.
  • Multiple classes differ only in their behavior, and you can use the policy pattern to dynamically select the specific behavior to be performed at run time.

26.4 JDK source code parsing

Policy mode in the Comparator. There’s a sort() method in the Arrays class that looks like this:

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); }}}Copy the code

Arrays is an environment role class, and this sort method can pass Arrays a new policy to sort by. Take the following test class for example.

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) {
                returno2 - o1; }}); System.out.println(Arrays.toString(data));//[12, 5, 4, 3, 2, 2, 1]}}Copy the code

When we call the Sort method of Arrays, the second argument passes a subimplementation of the Comparator interface. So the Comparator acts as an abstract policy role, and the concrete subimplementation class acts as a concrete policy role. The environment roles classes should be called with references to abstract policies. Does the Sort method of the Arrays class implement the compare() method using the Comparator child? Let’s move on to the sort() method of the TimSort class, which looks like this:

class TimSort<T> {
    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assertc ! =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++;
        }

        returnrunHi - lo; }}Copy the code

In that code, we’ll end up in countRunAndMakeAscending(). As we can see, only the compare method is used, so when we call arrays. sort we just pass the class object of the specific compare overwrite method, which is a mandatory subclass of the Comparator interface.

Write in the last

  • If my article is useful to you, please give me a click 👍, thank you 😊!
  • If you have any questions, please point them out in the comments section! 💪