Welcome to follow the official wechat account: FSA Full stack action 👋
I. Introduction of strategy mode
A Strategy Pattern defines a series of algorithms, encapsulates them one by one, and makes them interchangeable
-
The core of
- Context: Shields high-level modules from direct access to policies and algorithms and encapsulates possible changes
- Strategy Policy role: An abstract policy role is an abstraction of a policy or algorithm family. It defines the methods and attributes that each policy or algorithm must have
- ConcreteStrategy Concrete policy role: Used to implement operations in abstract policies, that is, implement concrete algorithms
-
Application scenarios
- Go out to travel, choose to ride a bicycle, by car, plane, etc., each kind of travel is a strategy
- LayoutManager in Java AWT
- If there are many classes in a system that are distinguished only by their behavior, then the policy pattern can be used
- If you don’t want to expose complex, algorithm-specific data structures, you can use policy patterns to encapsulate algorithms
-
advantages
- When a new concrete policy is added, the context can reference the instance of the new concrete policy without modifying the code of the context class
- Avoid multiple conditional statements if different policy patterns use multiple conditional statements, which can be bad for maintenance. Use this with factory mode to eliminate multiple layers of nesting of if-else code (factory mode mainly obtains different policies based on parameters).
-
disadvantages
- The number of policy classes will increase, and each policy is a class, which is very unlikely to be reused
- All behaviors and algorithms of the class are exposed. Too many behaviors lead to policy class expansion
In the JDK, Collections#sort(list, comparator) is the policy mode. The comparison logic is determined by the external pass.
Second, policy mode code implementation
Take e-commerce promotion as an example, a commodity, usually 800 yuan, catch up with the National Day promotion, there are three discount ways for users to choose:
- Do not use any discount
- Use a 20% discount
- Use coupons and discounts
Create commodity order class:
/** ** **@author GitLqr
*/
public class ProductOrder {
private float oldPrice;
private int userId;
private int productId;
public ProductOrder(float oldPrice, int userId, int productId) {
super(a);this.oldPrice = oldPrice;
this.userId = userId;
this.productId = productId; }... settter & getter ... }Copy the code
Create an abstract policy class where the purpose of the current policy is to calculate the discounted price:
/** * Abstract policy role: active policy **@author GitLqr
*/
public abstract class ActivityStrategy {
/** * calculate the order price */
public abstract double computePrice(ProductOrder productOrder);
}
Copy the code
Create a specific policy class that corresponds to the above three discounts:
/** * Specific policy: no activity **@author GitLqr
*/
public class NormalActivityStrategy extends ActivityStrategy {
@Override
public double computePrice(ProductOrder productOrder) {
returnproductOrder.getOldPrice(); }}/** * Specific strategy: discount activities **@author GitLqr
*/
public class DiscountActivityStrategy extends ActivityStrategy {
private float rate; / / discount
public DiscountActivityStrategy(float rate) {
super(a);this.rate = rate;
}
@Override
public double computePrice(ProductOrder productOrder) {
returnproductOrder.getOldPrice() * rate; }}/** * Specific strategy: coupon deduction activities **@author GitLqr
*/
public class VoucherActivityStrategy extends ActivityStrategy {
private float voucher;
public VoucherActivityStrategy(float voucher) {
super(a);this.voucher = voucher;
}
@Override
public double computePrice(ProductOrder productOrder) {
if (productOrder.getOldPrice() > voucher) {
return productOrder.getOldPrice() - voucher;
} else {
return 0; }}}Copy the code
Create context class:
Note: Shield the direct access of high-level modules to policies and algorithms, and encapsulate possible changes
/** * context: promotional context **@author GitLqr
*/
public class PromotionContext {
// Hold specific strategies
private ActivityStrategy activityStrategy;
public PromotionContext(ActivityStrategy activityStrategy) {
super(a);this.activityStrategy = activityStrategy;
}
// Calculate directly using specific policies
public double executeStrategy(ProductOrder productOrder) {
returnactivityStrategy.computePrice(productOrder); }}Copy the code
Use:
public static void main(String[] args) {
ProductOrder productOrder = new ProductOrder(800.9527.1001);
PromotionContext promotionContext;
double finalPrice;
/ / not activities
promotionContext = new PromotionContext(new NormalActivityStrategy());
finalPrice = promotionContext.executeStrategy(productOrder);
System.out.println("Normal price:" + finalPrice);
// Discounts
promotionContext = new PromotionContext(new DiscountActivityStrategy(0.8 f));
finalPrice = promotionContext.executeStrategy(productOrder);
System.out.println("Discounted price:" + finalPrice);
// Use a coupon
promotionContext = new PromotionContext(new VoucherActivityStrategy(100));
finalPrice = promotionContext.executeStrategy(productOrder);
System.out.println("Use coupon to offset price:" + finalPrice);
}
Copy the code
If this article is helpful to you, please click on my wechat official number: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, but also iOS, Python and other articles, which may have some skills you want to know about oh ~