Strategic design patterns — thoroughly explained
I. What is the strategy Design pattern
There are three types of design patterns: creative, behavioral, and structural. The strategy design pattern is behavioral. Why is it behavioral? Take a look at the following explanation:
1.1 What is a strategy?
What is strategy? For example: the way to get around: you can ride a bike, a motorcycle, drive a car, take a bus, take a train, a ship, a plane and so on. These are all travel strategies. Let’s look at the shopping malls for promotions: 20% off, 30% off, 30% off when you buy more than 100, 50% rebate when you buy more than 500, etc. No matter what kind of discount method, it is an algorithm, these algorithms are a strategy. Strategies are interchangeable at random. For example, the same shopping mall, today can be 20% off, tomorrow can be full of 100 30.
Strategy Design pattern: Define [a group of] algorithms, wrap [each] algorithm, and they are interchangeable, as shown in a UML diagram:
As you can see from the figure above, defining a policy design pattern requires four steps
- Policy interface class: abstracts policies and algorithms. Defines the algorithms and attributes that each policy and algorithm must have.
- Policy implementation class: policy, algorithm concrete implementation. There are several types of policy implementations that define several policy classes and implement policy methods
- Context: the Context class connects the preceding and the following. It blocks access to policies and algorithms by upper-level modules, encapsulating possible changes.
The policy method can have no arguments, but it must have a constructor, which determines the actual policy of the class. 4. Client class: The client invokes the Context class and specifies the class to invoke the policy. Therefore, users are required to know which policy classes are available in advance.
These are the four steps for implementing the strategy design pattern
Strategy design pattern code implementation
Let’s take the shopping mall promotion as an example, using the strategy design pattern to achieve. Now the shopping mall to promote sales, product promotion methods are: original price, discount (20% off, 70% off), full reduction (full 100 minus 30, full 100 minus 20) and so on. The specific way of promotion is strategy. Follow the four steps of the implementation step by step
2.1 Step 1: Define the interface class of shopping mall promotion
package com.lxl.www.designPatterns.strategy;
/** ** ** /
public interface IPromotionStrategy {
/** * promotion ** * Input is the original price, export is the promotion price *@return* /
Double promotion(PromotionVo promotionVo) throws Exception;
}
Copy the code
Here we define an interface class for a promotion strategy. And defined the promotion plan.
2.2 Step 2: Implementation class of promotion plan
There are three kinds of promotion programs: the first one: original price, the second one: discount, the third one: full reduction, let’s take a look at the first one: original price
package com.lxl.www.designPatterns.strategy;
/** * Normal selling price */
public class CommonPromotionStrategy implements IPromotionStrategy {
@Override
public Double promotion(PromotionVo promotionVo) {
returnpromotionVo.getOriginPrice(); }}Copy the code
The original price is the normal selling price. So, there’s no computational logic
Second, discount
package com.lxl.www.designPatterns.strategy;
/** * discount */
public class DiscountPromotionStrategy implements IPromotionStrategy {
@Override
public Double promotion(PromotionVo promotionVo) throws Exception {
if (promotionVo.getDiscount() < 0 || promotionVo.getDiscount() >=1) {throw new Exception("Please enter the correct discount");
}
returnpromotionVo.getOriginPrice() * promotionVo.getDiscount(); }}Copy the code
If there is a discount, the discount must be in the range of 0 to 1 and return to the discounted price at the end
The third kind, full subtraction
package com.lxl.www.designPatterns.strategy;
/** * full discount */
public class FullReductionPromotionStrategy implements IPromotionStrategy {
/** * full minus *@return
* @throws Exception
*/
@Override
public Double promotion(PromotionVo promotionVo) throws Exception {
if (promotionVo.getReduction() == null || promotionVo.getFull() == null) {
throw new Exception("Please check the full subtraction parameter");
}
Double price = promotionVo.getOriginPrice();
Double canPromotionPrice=promotionVo.getOriginPrice();
while(canPromotionPrice >= promotionVo.getFull()) {
price = price - promotionVo.getReduction();
canPromotionPrice -= promotionVo.getFull();
}
returnprice; }}Copy the code
So the full minus logic here is for every 100 minus 30, for 300 minus 90.
2.3 Step 3: Context Shopping mall promotion category
What kind of discount are the products in our store? There are promotion decisions in the mall
package com.lxl.www.designPatterns.strategy;
import org.springframework.beans.factory.annotation.Autowired;
/** ** shopping mall promotion */
public class MallPromotion {
@Autowired
private IPromotionStrategy promotion;
public MallPromotion(IPromotionStrategy promotion) {
this.promotion = promotion;
}
public Double activityPromotion(PromotionVo promotionVo) throws Exception {
return this.promotion.promotion(promotionVo); }}Copy the code
The promotion class defines a constructor that specifies the current promotion scheme.
2.4 Actual promotion plans for specific products
public static void main(String[] args) throws Exception {
PromotionVo promotionVo = new PromotionVo(300.0.0.8.100.0.30.0);
System.out.println("
========== Normal sale =========");
MallPromotion mallPromotionContext1 = new MallPromotion(new CommonPromotionStrategy());
System.out.println(mallPromotionContext1.activityPromotion(promotionVo));
System.out.println("< br > < br > = = = = = = = = = = 8 fold the = = = = = = = = =");
MallPromotion mallPromotionContext2 = new MallPromotion(new DiscountPromotionStrategy());
System.out.println(mallPromotionContext2.activityPromotion(promotionVo));
System.out.println("
========== full 100 minus 30=========");
MallPromotion mallPromotionContext3 = new MallPromotion(newFullReductionPromotionStrategy()); System.out.println(mallPromotionContext3.activityPromotion(promotionVo)); }}Copy the code
We can have any promotion plan we want. Just call the store promotion class and pass in the promotion policy.
The application of strategy design pattern
3.1 When to use it?
A system has many classes, and the difference between them is the difference in behavior. This is where the strategic design pattern can be used.
3.2 the advantages
- The policy pattern provides perfect support for the “open closed principle”, allowing users to choose algorithms or behaviors without modifying the existing system, or to flexibly add new ones.
- Algorithms can be switched without knowing the implementation of the algorithm
- Multiple conditional selection statements can be avoided using the policy pattern. Multiple conditional selection statements are hard coded and not easy to maintain.
- Better scalability and flexibility to add new algorithms or behaviors. It can also flexibly switch between algorithms or behaviors
3.3 disadvantages
- The policy design mode generates many specific policy classes. The client can use only one policy class at a time. It is not supported to use one policy class to complete some functions and then use another policy class to complete the rest functions.
- All policy classes need to be exposed. Because only when the client knows which policies are available can it know which one to use. This means that the client must understand the differences between these algorithms in order to choose the right one at the right time. In other words, the policy pattern only works if the client knows all the algorithms or behaviors.
4. Application scenarios
1. A system that needs to dynamically choose between several algorithms, the difference between which is only the algorithm or behavior, can use the strategy pattern, so that we can dynamically make an object choose one behavior among many behaviors. A system needs to dynamically choose one of several algorithms. 3. An object has many behaviors that, without a policy design pattern, would have to be implemented using multiple conditional selection statements. Using the policy pattern, these behaviors are transferred to the corresponding concrete policy class, avoiding the use of multiple conditional selection statements that are difficult to maintain.
5. Precautions
If a system has more than four policies, you need to consider using mixed mode to solve the problem of policy class inflation.
4. The application of strategy design mode combined with factory design mode
The mall promotion above. The end policy is all exposed to the client, which is not particularly client-friendly. We can encapsulate policies with simple factory design patterns.
package com.lxl.www.designPatterns.strategy;
import org.springframework.beans.factory.annotation.Autowired;
/** ** shopping mall promotion */
public class MallPromotionContext {
@Autowired
private IPromotionStrategy promotion;
public MallPromotionContext(IPromotionStrategy promotion) {
this.promotion = promotion;
}
public MallPromotionContext(Integer type) {
switch (type) {
case 1:
this.promotion = new CommonPromotionStrategy();
break;
case 2:
this.promotion = new DiscountPromotionStrategy();
break;
case 3:
this.promotion = new FullReductionPromotionStrategy();
break; }}public Double activityPromotion(PromotionVo promotionVo) throws Exception {
return this.promotion.promotion(promotionVo); }}Copy the code
The advantage of this encapsulation is that the client only needs to know what type of promotion strategy it wants, not the specific type of promotion strategy. Let’s look at the implementation of the policy code
public static void main(String[] args) throws Exception {
PromotionVo promotionVo = new PromotionVo(300.0.0.8.100.0.30.0);
System.out.println("
========== Normal sale =========");
MallPromotionContext mallPromotionContext1 = new MallPromotionContext(1);
System.out.println(mallPromotionContext1.activityPromotion(promotionVo));
System.out.println("< br > < br > = = = = = = = = = = 8 fold the = = = = = = = = =");
MallPromotionContext mallPromotionContext2 = new MallPromotionContext(2);
System.out.println(mallPromotionContext2.activityPromotion(promotionVo));
System.out.println("
========== full 100 minus 30=========");
MallPromotionContext mallPromotionContext3 = new MallPromotionContext(3);
System.out.println(mallPromotionContext3.activityPromotion(promotionVo));
}
Copy the code
In the basic policy design pattern, the responsibility for selecting the specific implementation to be used is taken by the client object and transferred to the Context object of the policy pattern, which does not relieve the pressure on the client to make choices. The combination of the strategic design pattern and the simple factory design pattern, choosing the specific implementation is also undertaken by the Context, which greatly relieves the responsibility of the client.