标签 : Java与设计模式
策略模式: 定义一系列的算法, 将其一个个 封装 起来, 并使它们可相互替换, 使得算法可独立于使用它的客户而变化.
(图片来源: 设计模式: 可复用面向对象软件的基础 )
策略模式对应于解决某一问题的一个 算法族 , 允许用户从该算法族中任选一个算法解决该问题, 同时可以方便的更换算法或者增加新的算法. 并由客户端决定调用哪个算法(核心: 分离算法, 选择实现 ).
案例: 商场打折 -策略可以简单分为: 原价购买、满减、返利三种策略:
抽象策略: 定义算法族中所有算法的公共接口, Context 使用这个接口来调用 ConcreteStrategy 定义的算法:
/**
* @author jifang
* @since 16/8/29 下午7:43.
*/
public interface Strategy {
double acceptCash(double money);
}
具体策略: 以 Strategy 接口实现某具体算法或行为:
// 正常收费
class Normal implements Strategy {
@Override
public double acceptCash(double money) {
return money;
}
}
// 打折收费
class Discount implements Strategy {
private double rate;
public Discount(double rate) {
if (rate > 1.0) {
throw new RuntimeException("折扣力度怎么能大于1.0?");
}
this.rate = rate;
}
@Override
public double acceptCash(double money) {
return money * rate;
}
}
// 返利收费
class Rebate implements Strategy {
private double cashState;
private double cashReturn;
public Rebate(double cashState, double cashReturn) {
this.cashState = cashState;
this.cashReturn = cashReturn;
}
@Override
public double acceptCash(double money) {
if (money > cashState) {
money -= Math.floor(money / cashState) * cashReturn;
}
return money;
}
}
上下文:
public class Context {
private Strategy strategy;
public void setStrategy(Type type, double... args) {
if (type == Type.NORMAL) {
strategy = new Normal();
} else if (type == Type.DISCOUNT) {
strategy = new Discount(args[0]);
} else if (type == Type.REBATE) {
strategy = new Rebate(args[0], args[1]);
}
}
public double getResult(double money) {
return strategy.acceptCash(money);
}
public enum Type {
NORMAL(0, "正常"),
DISCOUNT(1, "打折"),
REBATE(2, "返利");
private int value;
private String desc;
Type(int value, String desc) {
this.value = value;
this.desc = desc;
}
}
}
注: 将客户端需要选择具体 Strategy 的任务交给 Context 完成:
在 基础策略模式 中, 选择所用具体Strategy实现 的职责由Client承担, 并将其传递给 Context , 这种方案对Client的负担较重, 因此将 Context 与 简单工厂 融合, 选择算法实现的工作改由 Context 负责.
Client
仅与 Context 交互: 通常有一系列的 ConcreteStrategy 可供选择.
public class Client {
@Test
public void client() {
double money = 1000;
Context context = new Context();
context.setStrategy(Context.Type.NORMAL);
System.out.println("原价: [" + context.getResult(money) + "]");
context.setStrategy(Context.Type.REBATE, 100, 20);
System.out.println("满100返20: [" + context.getResult(money) + "]");
context.setStrategy(Context.Type.DISCOUNT, 0.8);
System.out.println("6折优惠: [" + context.getResult(money) + "]");
}
}
作用
场景
service() 方法). by 翡青