
一、介绍
所谓策略模式,指的是做某一件事时有多种选择(即策略),且不同的策略之间相互独立,而且无论使用哪种策略,得到的结果都是相同的
二、角色定义
Context封装角色
这个角色是策略模式中的重要组成部分,通常用于存储和传递策略对象,以及处理策略对象的交互逻辑。上下文对象在客户端的请求下,会调用合适的策略对象来执行相应的操作。
Strategy抽象策略角色
这个角色通常是一个接口,用于定义各种策略对象的共同方法。具体策略对象实现这个接口,并包含具体的算法实现。策略对象不持有任何上下文对象的状态,这样保证了策略对象的可复用性。
ConcreteStrategy具体策略角色
这个角色是实现策略接口的具体类,包含了具体的算法实现。具体策略对象通常会持有上下文对象的状态,以便在执行算法时能够访问和修改这些状态。

三、案例
定义抽象的策略接口
java
/**
* 支付策略接口
*/
public interface PayStrategy {
/**
* 实际支付金额计算
* @param money
*/
Double compute(Double money);
}
定义具体的支付策略类
java
/**
* 非会员计费策略
*/
public class Level0Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("非会员开始计费");
return money;
}
}
java
/**
* 初级会员计费策略
*/
public class Level1Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("初级会员开始计费");
return money*0.8;
}
}
java
/**
* 中级会员计费策略
*/
public class Level2Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("中级会员开始计费");
return money*0.7;
}
}
java
/**
* 高级会员计费策略
*/
public class Level3Strategy implements PayStrategy{
@Override
public Double compute(Double money) {
System.out.println("高级会员开始计费");
return money*0.5;
}
}
定义用于存储和传递策略的上下文
java
/**
* 支付策略上下文
*/
public class StrategyContent {
private PayStrategy payStrategy;
public StrategyContent(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
/**
* 支付方法
* @param money
* @return
*/
public Double pay(Double money){
return this.payStrategy.compute(money);
}
}
定义策略工厂类,用于生产具体的策略
java
/**
* 策略工厂
*/
public class PayStrategyFactory {
public static PayStrategy getStrategy(Member member){
PayStrategy payStrategy;
switch (member.getLevel()){
case "初级":
payStrategy=new Level1Strategy();
break;
case "中级":
payStrategy=new Level2Strategy();
break;
case "高级":
payStrategy=new Level3Strategy();
break;
default:
payStrategy=new Level0Strategy();
break;
}
return payStrategy;
}
}
编写客户端
java
@Data
@AllArgsConstructor
public class Member {
/**
* 会员姓名
*/
private String name;
/**
* 会员等级:非会员、初级、中级、高级
*/
private String level;
/**
* 支付金额
*/
private Double pay;
}
测试
java
public class Test {
public static void main(String[] args) {
Member member = new Member("小明", "初级", 100.00);
PayStrategy strategy = PayStrategyFactory.getStrategy(member);
StrategyContent strategyContent = new StrategyContent(strategy);
Double pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
member = new Member("小红", "中级", 100.00);
strategy = PayStrategyFactory.getStrategy(member);
strategyContent = new StrategyContent(strategy);
pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
member = new Member("铁蛋", "高级", 100.00);
strategy = PayStrategyFactory.getStrategy(member);
strategyContent = new StrategyContent(strategy);
pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
member = new Member("李刚", "非会员", 100.00);
strategy = PayStrategyFactory.getStrategy(member);
strategyContent = new StrategyContent(strategy);
pay = strategyContent.pay(member.getPay());
System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
}
}

四、适用场景
-
不同业务逻辑:在同一个业务逻辑中,可能会存在不同的策略或算法。例如,在电商网站中,可以根据不同的促销策略对商品进行不同的定价。在这种情况下,可以使用策略模式来封装不同的促销策略,并在运行时根据需要选择合适的策略。
-
数据排序策略:在处理大量数据时,可能需要使用不同的排序算法。例如,冒泡排序、选择排序、插入排序和二叉树排序等。在这种情况下,可以使用策略模式来定义不同的排序策略,并在运行时根据需要选择合适的策略。
-
算法切换:在某些情况下,可能需要根据不同的条件切换不同的算法。例如,在进行实时计算时,可能需要根据不同的输入数据选择不同的计算算法。在这种情况下,可以使用策略模式来封装不同的算法,并在运行时根据需要选择合适的算法。
-
行为切换:在系统中,可能需要根据不同的条件切换不同的行为。例如,在一个游戏中,可能需要根据不同的关卡选择不同的游戏策略。在这种情况下,可以使用策略模式来封装不同的游戏策略,并在运行时选择合适的行为
五、优缺点
优点
-
避免使用多重条件语句:策略模式通过使用策略类和上下文对象来避免使用多重条件语句,如if-else语句或switch-case语句。通过将算法的行为封装到策略类中,并在运行时根据客户端的需求选择相应的算法,策略模式使得代码更加简洁、易于维护和扩展。
-
提供可重用的算法族:策略模式通过定义抽象策略类和具体策略类,提供了一系列的算法实现。这些算法可以在不同的上下文中重复使用,通过组合和替换不同的策略对象来满足客户端的需求。
-
分离算法和客户端:策略模式将算法的实现和使用分离到具体的策略类和上下文对象中。客户端只需要与上下文对象进行交互,而不需要直接处理算法的实现细节。这种分离使得代码更加清晰、易于理解和维护。
-
支持对开闭原则的完美支持:策略模式可以在不修改原有代码的情况下,灵活地增加新的算法。通过定义新的策略类和上下文对象,可以轻松地将新的算法集成到现有系统中,满足新的需求。
-
将算法的使用放到环境类中:策略模式将算法的使用放到上下文对象中,而算法的实现则移到具体策略类中。这种分离使得代码更加清晰、易于管理和扩展。
-
客户端必须理解所有策略算法的区别:策略模式要求客户端必须理解所有可用的策略算法的区别,以便在适当的时候选择合适的算法。这可能增加了客户端的复杂性和学习成本。
缺点
- 可能导致过多的策略类:策略模式可能导致创建过多的策略类,每个算法都对应一个策略类。这可能会增加系统的复杂性和维护成本
六、总结
总之,策略模式是一种行为型设计模式,它通过封装一系列可重用的算法实现,并将它们组合到不同的上下文中,实现了算法的行为和使用的分离。这种模式使得代码更加灵活、易于维护和扩展,同时支持在不修改原有代码的情况下增加新算法,从而提高了代码的灵活性和可维护性