# 策略模式
# 简要回答
- 策略模式(Strategy Pattern)是行为型设计模式,它定义了一系列算法,将每个算法都封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户,也就是说这些算法完成的功能类型和对外接口是一样的,只是不同的策略引起环境角色表现出不同的行为。
- 优点:使用策略模式可以替代使用if...else或者switch...case语句,降低代码编写的复杂度,提高代码的可维护性。
- 缺点:需要定义大量的策略类,且每个策略类都要提供给客户端,只适用于客户端知道所有策略类的情况。
# 详细回答
- 策略模式主要由上下文、策略接口和具体策略类组成。Context类是用来操作策略的上下文环境类,持有抽象策略的引用,通过多态传进来不同的具体策略来调用不同策略的方法;策略接口定义了算法的接口或抽象类,声明所有具体策略必须实现的方法;具体的策略类实现了这个接口,实现具体算法的封装;
- 实现策略模式的步骤:
- 定义一个策略接口,声明算法的抽象方法。
- 创建具体的策略类,实现策略接口并封装具体的算法。
- 创建环境类,包含对策略接口的引用以及一个用于设置具体对象的方法。
- 在客户端中创建环境类的对象,并调用其方法来执行具体的算法。
# 代码示例
- 下面是一个简单的策略模式的示例,假设有一个商场销售系统,根据不同的促销策略计算最终价格:
// 策略接口
public interface PricingStrategy {
double calculatePrice(double price);
}
// 具体策略类:无折扣
public class NoDiscountStrategy implements PricingStrategy {
@Override
public double calculatePrice(double price) {
return price;
}
}
// 具体策略类:打九折
public class DiscountStrategy implements PricingStrategy {
@Override
public double calculatePrice(double price) {
return price * 0.9;
}
}
// 具体策略类:满减
public class CashbackStrategy implements PricingStrategy {
@Override
public double calculatePrice(double price) {
if (price >= 200) {
return price - 50;
} else {
return price;
}
}
}
// 环境类
public class ShoppingCart {
private PricingStrategy pricingStrategy;
public void setPricingStrategy(PricingStrategy pricingStrategy) {
this.pricingStrategy = pricingStrategy;
}
public double checkout(double totalPrice) {
return pricingStrategy.calculatePrice(totalPrice);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 选择无折扣策略
cart.setPricingStrategy(new NoDiscountStrategy());
double price1 = cart.checkout(100);
System.out.println("Total Price: " + price1); // 输出:Total Price: 100.0
// 选择打九折策略
cart.setPricingStrategy(new DiscountStrategy());
double price2 = cart.checkout(100);
System.out.println("Total Price: " + price2); // 输出:Total Price: 90.0
// 选择满减策略
cart.setPricingStrategy(new CashbackStrategy());
double price3 = cart.checkout(200);
System.out.println("Total Price: " + price3); // 输出:Total Price: 150.0
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 知识图解
- 策略模式结构图

# 使用场景
- 当需要动态切换算法时,可以使用策略模式。
- 如果代码中有多个条件语句,存在复杂条件判断时,可以使用策略模式简化代码。
- 使用策略模式可以避免与算法相关的数据结构暴露,只需使用抽象接口调用,无需知道实现细节。
- 如果有许多相关的类仅仅是行为不同,那么可以使用策略模式。
# 知识扩展
- 面试官可能追问:
- Q1:如何避免策略类过多的问题?
- 解决策略模式策略类过多的问题,核心有三层优化思路,首先最常用的是结合简单工厂模式,把所有策略对象的创建逻辑统一封装到策略工厂中,由工厂根据业务标识匹配并返回对应策略对象,客户端只需传入标识即可使用,无需感知所有策略类;其次进阶优化是在工厂中用Map容器做策略缓存,把策略标识和策略实例做键值对映射,项目启动时初始化存入 Map,获取策略时直接 O(1) 查询,彻底去掉 if-else/switch 分支判断,同时满足开闭原则;最后从根源上避免类膨胀,是对策略做复用与参数化抽离,很多策略类只是参数不同、核心逻辑一致,比如不同满减规则、不同计费标准,这种场景无需新建类,只需把可变参数抽离出来,通过构造器或方法传入策略类,一个策略类即可适配多套规则,从根本上减少策略类的数量。
评论
验证登录状态...