preface

In a recent interview, one of the interviewers asked me if I knew any design patterns. I talked about strategic patterns. Then he asked what kind of scenarios were used, and I told him that the JDK’s Collections utility class had a sort method that used the policy pattern. The Collections class in java.util package had a sort method that allowed us to customize the collation rules for Collections. This was the most straightforward application of the policy pattern. After saying that, he nodded and expected to be satisfied with my answer. Of course, I was just pretending to be forced on this interview question. After all, at the end of the interview, he said, please go back and wait for the news.

What are strategic patterns

Without further discussion, today we are going to look at the definition of strategic patterns in our design Patterns series.

Policy pattern, also known as policy pattern, the idea is to define a set of algorithms, encapsulate each algorithm, and make them interchangeable. Its biggest feature is that the algorithm can be changed without affecting the client, so as to change different functions. For example, the sort method takes a parameter to a Comparator interface. It doesn’t care about the implementation of the Comparator interface, as long as the parameter is of that interface type. We can implement the Comparator interface ourselves and define the desired collation in its implementation class, such as ascending or descending order for a field in a collection. This is a direct application of the policy pattern.

Write some code to express it briefly:

public static void main(String[] args) {
   
    List<Integer> list1 = new ArrayList<>();
    list1.add(1);
    list1.add(20);
    list1.add(3);
    
    Collections.sort(list1, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            returno1 - o2; }}); System.out.println("Ascending = = = = = = =" + list1.toString());

    Collections.sort(list1, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            returno2 - o1; }}); System.out.println("Descending = = = = = = =" + list1.toString());
}
Copy the code

composition

With the definition and examples of the policy pattern, let’s look at the constituent roles of the policy pattern.

The policy pattern contains three roles:

  • Strategy Abstract Policy role: An abstraction of a policy or algorithm family, usually an interface, that defines the methods and attributes that each policy or algorithm must have. Using the collection sorting example above, this role corresponds to the Comparator interface.
  • ConcreteStrategy Concrete Policy Role: Implements operations in an abstract policy. This class contains concrete algorithms. That is, our custom Comparator implementation class.
  • Context encapsulates roles: This is also called a Context role, and internally holds a reference to an abstract role for the client to invoke. This role corresponds to the Collections utility class itself, which holds a reference to the Comparator interface and can receive our custom concrete implementation classes.

With these three roles, we can simply list the class diagram of the policy pattern:

Generic class code

Abstract policy roles:

Public interface Strategy {// Algorithm rules of the policy mode public voiddoSomething();
}
Copy the code

Specific policy roles:

public class ConcreteStrategy1 implements Strategy {
    public void doSomething() {
        System.out.println("Algorithm for specific Strategy 1.");
    }
}

public class ConcreteStrategy2 implements Strategy {
    public void doSomething() {
        System.out.println("Algorithm for Specific Strategy 2."); }}Copy the code

Encapsulating roles:

Public Class Context {private Strategy Strategy = null; Public Context(strategy_strategy) {this. Strategy = _strategy; } // Encapsulate the policy method public voiddoAnythinig() { this.strategy.doSomething(); }}Copy the code

After the three roles are established, when the client wants to call, first determine which specific policy to use, create the corresponding policy role object, and then pass in the encapsulated role, the specific code is as follows:

Public Class Client {public static void main(String[] args) {// Declare a concrete Strategy Strategy = new ConcreteStrategy1(); Context = new Context(strategy); // Execute the wrapped method context.doanythinig (); }}Copy the code

conclusion

So much for the introduction of the strategic pattern. The strategic pattern is a relatively simple design pattern, but it is often used in actual projects. For example, one of the projects in my previous company used the strategic pattern.

That project belongs to the system of e-commerce, and each commodity has its own coupon. When placing an order and settling the amount, it is necessary to calculate the sum of the price of the commodity and the coupon. There is a headache here, because each commodity has a unique coupon. Adding a product or coupon would require reworking of the settlement logic of the order, which is clearly against the open and close principle. In response to this situation, we adopted the idea of the policy pattern and modified the code as follows.

Define an abstract policy role with commodity and coupon properties

2. At the same time, create specific strategic roles for each type of commodity and define their own unique calculation coupon strategy

3. In the method of placing orders and settling accounts, create corresponding specific strategy objects according to the types of commodities and coupons, pass the objects into an encapsulation role and call the method of settling accounts

In this way, the corresponding amount can be calculated according to different kinds of commodities and coupons, and the code packaging becomes more abstract, and the specific strategies of commodities are independent of each other, not affecting the whole body, saving worry and effort.

Above strategy model is a specific application, of course, the application of the strategy pattern still has a lot of, I will introduce one of the usage scenarios, and through the actual example let everybody feel the charm of design pattern, after all, find one thousand days, fighting at that time, the more we learn the theoretical knowledge is not just for one day to be real?