1.定义
策略模式又叫政策模式,它是将定义的算法家族,封装起来,使他们之间可以互相替换,从事算法的变化不影响使用算法的用户,属于行为型模式。
策略模式就是面向对象的继承和多态机制,让一种行为在不同的场景下有不同的实现
2.策略模式的应用场景
1.不同薪资纳税比例不一样
2.在线支付 可以选择多种支付工具
策略模式可以解决在多中类似的算法情况下,使用if...else或switch...case所带来的复杂性和臃肿:
1.针对同一类型问题,有多中处理方式,每一种都能独立解决问题
2.算法需要自由切换的场景
3.需要屏蔽算法规则的场景
3.策略模式的三种角色
1.上下文角色(context):用来操作策略模式的上下文场景,屏蔽高层模块对策略、算法的直接访问封装可能存在的变化
2.抽象策略模式:规定策略或算法的行为
3.具体策略角色:具体的策略或算法实现
4.demo
不同的优惠策略
/**
* create by yufeng on 2021/7/5 17:00
*/
public interface IPromotionStrategy {
void doPromotion();
}
/**
* create by yufeng on 2021/7/5 17:13
*/
public class CashbackStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("返现,直接打款到支付宝账号");
}
}
/**
* create by yufeng on 2021/7/5 17:15
*/
public class CouponStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("使用优惠券抵扣");
}
}
/**
* create by yufeng on 2021/7/5 17:20
*/
public class EmptyStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("无优惠");
}
}
/**
* create by yufeng on 2021/7/5 17:22
*/
public class GroupbuyStrategy implements IPromotionStrategy {
public void doPromotion() {
System.out.println("5人成团,可以优惠");
}
}
/**
* create by yufeng on 2021/7/5 17:30
*/
public class PromotionStrategyFacory {
private static Map<String,IPromotionStrategy> PROMOTIONS = new HashMap<String,IPromotionStrategy>();
static {
PROMOTIONS.put(PromotionKey.COUPON,new CouponStrategy());
PROMOTIONS.put(PromotionKey.CASHBACK,new CashbackStrategy());
PROMOTIONS.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
}
private static final IPromotionStrategy EMPTY = new EmptyStrategy();
private PromotionStrategyFacory(){}
public static IPromotionStrategy getPromotionStrategy(String promotionKey){
IPromotionStrategy strategy = PROMOTIONS.get(promotionKey);
return strategy == null ? EMPTY : strategy;
}
private interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBUY = "GROUPBUY";
}
public static Set<String> getPromotionKeys(){
return PROMOTIONS.keySet();
}
}
/**
* create by yufeng on 2021/7/5 17:32
*/
public class Test {
public static void main(String[] args) {
String promotionKey = "COUPON";
IPromotionStrategy promotionStrategy = PromotionStrategyFacory.getPromotionStrategy(promotionKey);
promotionStrategy.doPromotion();
}
}
执行结果:
使用优惠券抵扣
支付场景
/**
* create by yufeng on 2021/7/5 18:13
*/
public class MsgResult {
private int code;
private Object data;
private String msg;
public MsgResult(int code, String msg, Object data) {
this.code = code;
this.data = data;
this.msg = msg;
}
@Override
public String toString() {
return "MsgResult{" +
"code=" + code +
", data=" + data +
", msg='" + msg + '\'' +
'}';
}
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public abstract class Payment {
public abstract String getName();
//通用逻辑放到抽象类里面实现
public MsgResult pay(String uid, double amount){
//余额是否足够
if(queryBalance(uid) < amount){
return new MsgResult(500,"支付失败","余额不足");
}
return new MsgResult(200,"支付成功","支付金额" + amount);
}
protected abstract double queryBalance(String uid);
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public class AliPay extends Payment {
public String getName() {
return "支付宝";
}
protected double queryBalance(String uid) {
return 900;
}
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public class WechatPay extends Payment {
public String getName() {
return "微信支付";
}
protected double queryBalance(String uid) {
return 263;
}
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public class UnionPay extends Payment {
public String getName() {
return "银联支付";
}
protected double queryBalance(String uid) {
return 120;
}
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String UNION_PAY = "UnionPay";
public static final String DEFAULT_PAY = ALI_PAY;
private static Map<String,Payment> strategy = new HashMap<String,Payment>();
static {
strategy.put(ALI_PAY,new AliPay());
strategy.put(JD_PAY,new JDPay());
strategy.put(WECHAT_PAY,new WechatPay());
strategy.put(UNION_PAY,new UnionPay());
}
public static Payment get(String payKey){
if(!strategy.containsKey(payKey)){
return strategy.get(DEFAULT_PAY);
}
return strategy.get(payKey);
}
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public MsgResult pay(){
return pay(PayStrategy.DEFAULT_PAY);
}
public MsgResult pay(String payKey){
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用" + payment.getName());
System.out.println("本次交易金额为" + amount + ",开始扣款");
return payment.pay(uid,amount);
}
}
/**
* create by yufeng on 2021/7/5 18:13
*/
public class Test {
public static void main(String[] args) {
Order order = new Order("1","2020031401000323",324.5);
System.out.println(order.pay(PayStrategy.UNION_PAY));
}
}
类图:
image.png
5.优缺点
优点:
符合开闭原则
避免过多if...else switc..case
使用策略模式提高了算法的保密性和安全性
缺点:
客户端必须知道所有策略,并自行决定用哪个策略
代码中会产生非常多的策略类,增加维护难度