Strategy mode
brief introduction
The policy pattern is the packaging of the algorithm. It separates the responsibility of using the algorithm from the algorithm itself and delegates it to different objects for management. Policy patterns usually package a series of algorithms into a series of policy classes as subclasses of an abstract policy class. In a word, "prepare a set of algorithms and package each algorithm so that they can be interchanged". The following is a schematic implementation to explain the structure of the policy pattern example.
role
-
Context role: holds a reference to Strategy.
-
Abstract strategy role: 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 role: encapsulates related algorithms or behaviors.
code
Project structure
Instance scenario
Suppose we want to design a shopping cart system of e-commerce website selling all kinds of books. The simplest case is to multiply the unit price of all goods by the quantity, but the actual situation must be more complicated than this. For example, this website may provide 20% promotion discount for all senior members; Offer 10% promotion discount for intermediate members; There is no discount for junior members.
According to the description, the discount is performed according to one of the following algorithms:
-
Algorithm 1: there is no discount for junior members.
-
Algorithm 2: offer 10% promotion discount to intermediate members.
-
Algorithm 3: offer 20% promotion discount to senior members.
The structure diagram of using policy mode is as follows:
Abstract discount class
public interface MemberStrategy { /** * Calculate the price of books * @param booksPrice Original price of books * @return Calculate the discounted price */ public double calcPrice(double booksPrice); }
Discount category
/** * Junior member discount */ public class PrimaryMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("There is no discount for junior members"); return booksPrice; } } /** * Intermediate member discount */ public class IntermediateMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("The discount for intermediate members is 10%"); return booksPrice * 0.9; } } /** * Premium member discount */ public class AdvancedMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("The discount for senior members is 20%"); return booksPrice * 0.8; } }
Price category
public class Price { //Hold a specific policy object private MemberStrategy strategy; /** * Constructor, passing in a specific policy object * @param strategy Specific policy objects */ public Price(MemberStrategy strategy){ this.strategy = strategy; } /** * Calculate the price of books * @param booksPrice Original price of books * @return Calculate the discounted price */ public double quote(double booksPrice){ return this.strategy.calcPrice(booksPrice); } }
Test class
public class ApiTest { @Test public void testCommand(){ //Select and create the policy object you want to use MemberStrategy strategy = new AdvancedMemberStrategy(); //Create environment Price price = new Price(strategy); //Calculate price double quote = price.quote(300); System.out.println("The final price of the book is:" + quote); } }
advantage
- The policy pattern provides a way to manage related algorithm families. The hierarchy of policy classes defines a family of algorithms or behaviors. Proper use of inheritance can move public code to the parent class, so as to avoid code duplication.
- Using the policy pattern avoids the use of multiple conditional (if else) statements. Multiple conditional statements are not easy to maintain. They mix the logic of which algorithm or behavior to adopt with the logic of algorithm or behavior. They are all listed in a multiple conditional statement, which is primitive and backward than the method of inheritance.
shortcoming
- The client must know all policy classes and decide which policy class to use. This means that the client must understand the differences between these algorithms in order to select the appropriate algorithm class in time. In other words, the policy pattern applies only when the client knows the algorithm or behavior.
- Because the policy pattern encapsulates each specific policy implementation into a class, if there are many alternative policies, the number of objects will be considerable.