一、定义及应用场景
1、定义
其思想是针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能
2、应用场景
- 假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。
- 一个系统需要动态地在几种算法中选择一种。
二、案例(一)
去商场买东西进行打折销售:领取优惠券抵扣、返现促销、拼团优惠
最终得结果都是付钱 但是没有优惠政策都不相同
1、促销策略抽象
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 19:57
* @description: 促销策略抽象
*/
public interface PromotionStrategy {
void doPromotion();
}
2、各种优惠政策
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 19:59
* @description: 返现促销策略
*/
public class CashbackStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("返现促销策略---");
}
}
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 19:58
* @description: 优惠卷优惠
*/
public class CouponStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("使用优惠卷进行优惠----");
}
}
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:00
* @description: 无优惠策略
*/
public class EmptyStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("无优惠策略-----");
}
}
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 19:59
* @description: 拼团策略
*/
public class GroupbuyStrategy implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("拼团策略------");
}
}
3、促销策略工厂
package com.ckw.strategy.pay.promotion;
import java.util.HashMap;
import java.util.Map;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:02
* @description: 促销策略工厂
*/
public class PromotionStrategyFactory {
private interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBUY = "GROUPBUY";
}
private static Map<String,PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String, PromotionStrategy>();
private static final PromotionStrategy NON_PROMOTION = new EmptyStrategy();
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
}
//根据传入得优惠策略返回对应得优惠策略算法
public static PromotionStrategy getPromotionStrategy(String promotionKey){
PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
}
}
4、促销活动
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:01
* @description: 优惠活动
*/
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
//执行优惠活动
public void execute(){
promotionStrategy.doPromotion();
}
}
5、测试
package com.ckw.strategy.pay.promotion;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:01
* @description: 优惠活动
*/
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
//执行优惠活动
public void execute(){
promotionStrategy.doPromotion();
}
}
三、案例(二)
小伙伴们都 用过支付宝、微信支付、银联支付以及京东白条。一个常见的应用场景就是大家在下单 支付时会提示选择支付方式,如果用户未选,系统也会默认好推荐的支付方式进行结算
1、创建支付渠道Payment
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:15
* @description: 支付渠道
*/
public abstract class Payment {
//支付类型
public abstract String getName();
//查询余额
protected abstract double queryBalance(String uid);
//扣款支付
public PayState pay(String uid,double amount) {
if(queryBalance(uid) < amount){
return new PayState(500,"支付失败","余额不足");
}
return new PayState(200,"支付成功","支付金额:" + amount);
}
}
2、创建支付方式
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:19
* @description: 支付宝支付
*/
public class AliPay extends Payment {
@Override
public String getName() {
return "支付宝";
}
@Override
protected double queryBalance(String uid) {
return 900;
}
}
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:20
* @description: 京东支付
*/
public class JDPay extends Payment {
@Override
public String getName() {
return "京东支付";
}
@Override
protected double queryBalance(String uid) {
return 800;
}
}
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:22
* @description: 银联支付
*/
public class UnionPay extends Payment {
@Override
public String getName() {
return "银联支付";
}
@Override
protected double queryBalance(String uid) {
return 1100;
}
}
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:21
* @description: 微信支付
*/
public class WechatPay extends Payment {
@Override
public String getName() {
return "微信支付";
}
@Override
protected double queryBalance(String uid) {
return 1000;
}
}
3、创建支付状态
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:17
* @description: 支付完成以后得状态
*/
public class PayState {
private int code;
private String data;
private String msg;
public PayState(int code, String data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
}
@Override
public String toString() {
return "支付状态{" +
"code=" + code +
", data='" + data + '\'' +
", 交易详情='" + msg + '\'' +
'}';
}
}
4、支付策略管理类
package com.ckw.strategy.pay.payport;
import java.util.HashMap;
import java.util.Map;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:23
* @description: 支付策略管理类
*/
public class PayStrategy {
public static final String ALI_PAY = "AliPay";
public static final String JD_PAY = "JdPay";
public static final String UNION_PAY = "UnionPay";
public static final String WECHAT_PAY = "WechatPay";
public static final String DEFAULT_PAY = ALI_PAY;
private static Map<String,Payment> payStrategy = new HashMap<String,Payment>();
static {
payStrategy.put(ALI_PAY,new AliPay());
payStrategy.put(WECHAT_PAY,new WechatPay());
payStrategy.put(UNION_PAY,new UnionPay());
payStrategy.put(JD_PAY,new JDPay());
}
//执行支付
public static Payment get(String payKey){
if(!payStrategy.containsKey(payKey)){
return payStrategy.get(DEFAULT_PAY);
}
return payStrategy.get(payKey); }
}
5、创建订单
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:26
* @description: 订单
*/
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;
}
//完美地解决了 switch 的过程,不需要在代码逻辑中写 switch 了
// 更不需要写 if else if
//默认支付方式
public PayState pay(){
return pay(PayStrategy.DEFAULT_PAY);
}
//自己选择支付方式
public PayState pay(String payKey){
Payment payment = PayStrategy.get(payKey);
System.out.println("欢迎使用" + payment.getName());
System.out.println("本次交易金额为:" + amount + ",开始扣款...");
return payment.pay(uid,amount);
}
}
6、测试
package com.ckw.strategy.pay.payport;
/**
* @author ckw
* @version 1.0
* @date 2020/6/12 20:31
* @description:
*/
public class PayStrategyTest {
public static void main(String[] args) {
Order order = new Order("111", "111", 500);
PayState jdPay = order.pay("JdPay");
System.out.println(jdPay);
}
}
6、结果
四、优缺点
1、优点
- 策略模式符合开闭原则。
- 避免使用多重条件转移语句,如 if…else…语句、switch 语句
- 使用策略模式可以提高算法的保密性和安全性。
2、缺点
- 客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
- 代码中会产生非常多策略类,增加维护难度