代理模式的定义:策略模式是一种行为型模式,定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
比如商场收银时如何促销,用打折还是返利,其实都是一些算法,这些算法本身就是一种策略,这些算法是随时都可以互相替换的,这就是变化点,而封装变化是我们面向对象的一种很重要的思维方式
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fNJY0iFC-1656173992963)(/var/folders/fj/225wqvz13hq0tflcnkl4y_v40000gn/T/abnerworks.Typora/image-20220625215252869.png)]](https://1000bd.com/contentImg/2022/06/27/205756134.png)
Strategy 类,定义所有支持的算法的公共接口
/**
* 抽象策略类
*/
public abstract class Strategy {
public abstract void algorithmInterface();
}
ConcreteStrategy,封装了具体的算法或行为,继承于 Strategy
/**
* 具体算法 A
*/
public class ConcreteStrategyA extends Strategy{
/**
* 算法 A 实现
*/
@Override
public void algorithmInterface() {
System.out.println("算法 A 实现");
}
}
/**
* 具体算法 B
*/
public class ConcreteStrategyB extends Strategy {
/**
* 算法 B 实现
*/
@Override
public void algorithmInterface() {
System.out.println("算法 B 实现");
}
}
/**
* 具体算法 C
*/
public class ConcreteStrategyC extends Strategy {
/**
* 算法 C 实现
*/
@Override
public void algorithmInterface() {
System.out.println("算法 C 实现");
}
}
Context,用一个 ConcreteStrategy 来配置,维护一个对 Strategy 对象的引用
/**
* 上下文
*/
public class Context {
private Strategy strategy;
public Context() {
}
/**
* 初始化时传入具体的策略对象
* @param strategy 具体的策略对象
*/
public Context(Strategy strategy) {
this.strategy = strategy;
}
/**
* 上下文接口
*/
public void contextInterface() {
strategy.algorithmInterface();
}
}
调用方代码
public class StrategyTest {
/**
* 因为实例化不同的策略,所以在调用 context.contextInterface(); 时,得到的结果不同
*/
public static void main(String[] args) {
Context context;
context = new Context(new ConcreteStrategyA());
context.contextInterface();
context = new Context(new ConcreteStrategyB());
context.contextInterface();
context = new Context(new ConcreteStrategyC());
context.contextInterface();
}
}
优点:
缺点:
比如商场使用现金收银时,有正常收费 CashNormal、打折收费 CashRebate、和返利收费 CashReturn 三个策略,也就是策略模式中的具体算法,我们使用策略模式来做这样一个设计
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-117HJUM2-1656173992963)(/var/folders/fj/225wqvz13hq0tflcnkl4y_v40000gn/T/abnerworks.Typora/image-20220625225513714.png)]](https://1000bd.com/contentImg/2022/06/27/205756338.png)
现金收费抽象类
/**
* 抽象现金策略,收取现金,返回价格
*/
public abstract class CashStrategy {
/**
* 接收现金
* @param money 接收的现金金额
* @param moneyRebate 打折率
* @param moneyCondition 返利条件
* @param moneyReturn 返利值
* @return 最后的金额
*/
public abstract BigDecimal acceptCash(BigDecimal money, Double moneyRebate, Double moneyCondition, Double moneyReturn);
/**
* 策略类型
* @return 策略类型
*/
public abstract String type();
}
正常收费策略
/**
* 正常收费子类,原价返回
*/
@Component
public class CashNormalStrategy extends CashStrategy {
@Override
public BigDecimal acceptCash(BigDecimal money, Double moneyRebate, Double moneyCondition, Double moneyReturn) {
return money;
}
@Override
public String type() {
return "normal";
}
}
打折收费策略
/**
* 打折收费算法,初始化传入折扣,返回打折后金额
*/
@Component
public class CashRebateStrategy extends CashStrategy {
@Override
public BigDecimal acceptCash(BigDecimal money, Double moneyRebate, Double moneyCondition, Double moneyReturn) {
return money.multiply(BigDecimal.valueOf(moneyRebate > 0 ? moneyRebate : 1.0d)).setScale(2);
}
@Override
public String type() {
return "rebate";
}
}
返利收费策略
/**
* 返利收费算法,初始化传入返利条件和返利值
*/
@Component
public class CashReturnStrategy extends CashStrategy {
@Override
public BigDecimal acceptCash(BigDecimal money, Double moneyRebate, Double moneyCondition, Double moneyReturn) {
BigDecimal result = money;
BigDecimal condition = BigDecimal.valueOf(moneyCondition == null ? 300.0d : moneyCondition);
BigDecimal returnMoney = BigDecimal.valueOf(moneyReturn == null ? 100.0d : moneyReturn);
// 如果大于返利条件,要减去返利值
if (money.compareTo(condition) > -1) {
result = money.subtract(money.divideAndRemainder(condition)[0].multiply(returnMoney));
}
return result.setScale(2);
}
@Override
public String type() {
return "return";
}
}
现金收费决策,根据类型选择策略
/**
* 现金策略决策,根据策略类型获取不同策略
*/
@Component
public class CashStrategyDecider {
@Resource
private CashNormalStrategy normalStrategy;
@Resource
private CashRebateStrategy rebateStrategy;
@Resource
private CashReturnStrategy returnStrategy;
public CashStrategy decideCashStrategy(String strategyType) {
if (strategyType == null ) {
return normalStrategy;
}
if (strategyType.equals(rebateStrategy.type())) {
return rebateStrategy;
} else {
// todo 扩展点
if (strategyType.equals(returnStrategy.type())) {
return returnStrategy;
}
}
return normalStrategy;
}
}
调用代码:
public class CashStrategyTest extends BaseTest {
@Resource
private CashStrategyDecider cashStrategyDecider;
@Test
public void cashStrategyTest() {
CashStrategy cashStrategy;
// 默认算法
cashStrategy = cashStrategyDecider.decideCashStrategy("");
BigDecimal defaultResult = cashStrategy.acceptCash(new BigDecimal(200), null, null, null);
System.out.println("使用默认算法得到的金额为" + defaultResult.doubleValue()); // 使用默认算法得到的金额为200.0
// 打折算法
cashStrategy = cashStrategyDecider.decideCashStrategy("rebate");
BigDecimal rebateResult = cashStrategy.acceptCash(new BigDecimal(200), 0.8d, null, null);
System.out.println("使用打折算法得到的金额为" + rebateResult.doubleValue()); // 使用打折算法得到的金额为160.0
// 返利算法
cashStrategy = cashStrategyDecider.decideCashStrategy("return");
BigDecimal returnResult = cashStrategy.acceptCash(new BigDecimal(500), null, 300d, 100.0d);
System.out.println("使用返利算法得到的金额为" + returnResult.doubleValue()); // 使用返利算法得到的金额为400.0
}
}