设计模式--策略模式

一、定义及应用场景

1、定义

其思想是针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能

2、应用场景

  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、优点

  1. 策略模式符合开闭原则。
  2. 避免使用多重条件转移语句,如 if…else…语句、switch 语句
  3. 使用策略模式可以提高算法的保密性和安全性。

2、缺点

  1. 客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
  2. 代码中会产生非常多策略类,增加维护难度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值