前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式(一) 支付策略模式

设计模式(一) 支付策略模式

作者头像
用户1518699
发布2019-07-15 15:59:23
1.7K0
发布2019-07-15 15:59:23
举报
文章被收录于专栏:nice_每一天nice_每一天

使用场景

公司最近在做直播功能,底层原来有一套直播API,现在新增一套网宿直播API。 考虑以后的扩展性,需要将两套API进行统一管理。现在以网上的支付方式演示我对策略模式的理解。

支付方式

我们知道网上有很多支付方式。支付宝、微信、银行卡、花呗... 我们以三种支付方式进行演示。

策略模式的组成有三部分

环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据,在上一个例子中相当于Staff。

抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法,在上一个例子中相当于GrantReward。 具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法,在上一个例子中相当于GrantSuger,GrantMoonCake,GrantNone。

支付方式的组成也有三部分

支付策略接口(PayStrategy):定义支付方式 具体支付方式(AliPayStrategy、WxPayStrategy、CardPayStrategy):具体的支付算法 支付策略上下文(PayStrategyContent):管理所有支付方式的引用,并根据用户选择引用对应的支付方式。

代码实现

支付策略接口(PayStrategy)

代码语言:javascript
复制
 1 /**
 2  * 支付策略接口
 3  * @author JinXing
 4  * @date 2019/7/12 13:58
 5  */
 6 public interface PayStrategy {
 7 
 8 
 9 
10     /**
11      *
12      * 选择支付方式
13      * 支付宝
14      * 微信
15      * 银行卡
16      * @return RemoteResult
17      */
18     RemoteResult<String> toPayHtml();
19 
20 
21 }

具体支付方式(AliPayStrategy)

代码语言:javascript
复制
 1 /**
 2  * 阿里pay
 3  * @author JinXing
 4  * @date 2019/7/12 14:36
 5  */
 6 @Service
 7 public class AliPayStrategy implements PayStrategy {
 8 
 9     @Override
10     public RemoteResult<String> toPayHtml() {
11 
12         System.out.println("现在采用的支付方式为:支付宝支付......");
13 
14         return null;
15     }
16 }

具体支付方式(WxPayStrategy)

代码语言:javascript
复制
 1 /**
 2  * 微信支付
 3  * @author JinXing
 4  * @date 2019/7/12 14:36
 5  */
 6 
 7 @Service
 8 public class WxPayStrategy implements PayStrategy {
 9 
10     @Override
11     public RemoteResult<String> toPayHtml() {
12 
13         System.out.println("现在采用的支付方式为:微信支付......");
14 
15         return null;
16     }
17 }

具体支付方式(CardPayStrategy)

代码语言:javascript
复制
 1 /**
 2  * 银行卡支付
 3  * @author JinXing
 4  * @date 2019/7/12 14:36
 5  */
 6 
 7 @Service
 8 public class CardPayStrategy implements PayStrategy {
 9 
10     @Override
11     public RemoteResult<String> toPayHtml() {
12 
13         System.out.println("现在采用的支付方式为:银行卡支付......");
14 
15         return null;
16     }
17 }

支付策略上下文(PayStrategyContent)

代码语言:javascript
复制
/**
 * 支付策略上下文
 * @author JinXing
 * @date 2019/7/12 14:39
 */

@Component
public class PayStrategyContent {


    /** 策略实例集合 */
    private ConcurrentHashMap<String, PayStrategy> strategyMap = new ConcurrentHashMap<>(20);

    /**
     * 注入策略实例
     * 如果使用的是构造器注入,可能会有多个参数注入进来。
     *
     * 如果使用的是field反射注入
     *
     * 如果使用的是setter方法注入,那么你将不能将属性设置为final。
     *
     * @param strategyMap
     *         注意注入类型要是Map基础类型
     */
    @Autowired
    public PayStrategyContent(Map<String, PayStrategy> strategyMap) {
        //清空集合数据
        this.strategyMap.clear();

        if (!CollectionUtils.isEmpty(strategyMap)) {
            strategyMap.forEach((beanName, payStrategy) -> {
                if (StringUtils.isEmpty(beanName) || payStrategy == null) {
                    return;
                }
                this.strategyMap.put(beanName.toLowerCase(), payStrategy);
            });
        }
    }


    /**
     * 选择支付方式
     * 支付宝、微信、银行卡
     *
     * @param paymentEnums
     *
     * @return RemoteResult
     */
    RemoteResult<String> toPayHtml(PaymentEnums paymentEnums) {

        if (CollectionUtils.isEmpty(strategyMap)) {
            return new RemoteResult<String>().error("策略实例集合初始化失败,请检查是否正确注入!");
        }

        return this.strategyMap.get(paymentEnums.getBeanName()).toPayHtml();
    }

}

支付方式枚举(PaymentEnums)

代码语言:javascript
复制
**
 * 支付方式枚举对象
 * code -> 支付方式别名
 * beanName -> 实例的名称
 *
 * @author JinXing
 * @date 2019/7/12 14:40
 */
public enum PaymentEnums {

    /** 支付方式 */
    ALI_PAY("ali_pay", AliPayStrategy.class.getSimpleName()),
    WX_PAY("WX_PAY", WxPayStrategy.class.getSimpleName()),
    CARD_PAY("card_pay", CardPayStrategy.class.getSimpleName()),

    ;

    /** 枚举定义+描述 */
    private String code;
    private String beanName;

    PaymentEnums(String code, String beanName) {
        this.code = code;
        this.beanName = StringUtils.isNotEmpty(beanName)?beanName.toLowerCase():null;
    }


    /** 根据code获取对应的枚举对象 */
    public static PaymentEnums getEnum(String code) {
        PaymentEnums[] values = PaymentEnums.values();
        if (null != code && values.length > 0) {
            for (PaymentEnums value : values) {
                if (value.code.equals(code)) {
                    return value;
                }
            }
        }
        return null;
    }

    /** 该code在枚举列表code属性是否存在 */
    public static boolean containsCode(String code) {
        PaymentEnums anEnum = getEnum(code);
        return anEnum != null;
    }

    /** 判断code与枚举中的code是否相同 */
    public static boolean equals(String code, PaymentEnums calendarSourceEnum) {
        return calendarSourceEnum.code.equals(code);
    }


    public String getCode() {
        return code;
    }

    public String getBeanName() {
        return beanName;
    }
}

结果集包装类(RemoteResult)

代码语言:javascript
复制
 1 /**
 2  * <pre>
 3  * 远程接口值对象,此对象使用说明
 4  * 使用时,判断isSuccess返回值,true表示业务成功、false表示接口调用失败
 5  * errorCode,用于判断失败原因(非系统错误),系统预设错误码,用负数表示:-1表示参数不合法,用户自定义错误码使用正数表示,0表示无错误
 6  * </pre>
 7  *
 8  * @author jx
 9  * @param <T>
10  */
11 
12 
13 public class RemoteResult<T> implements Serializable {
14 
15     private static final long serialVersionUID = 1L;
16     /** 接口调用是否成功(业务),系统错误、业务失败都将返回false */
17     private boolean isSuccess = true;
18     /** 自定义错误信息,发生可处理错误时,返回自定义信息 */
19     private String errorMsg = "ok";
20     /** 接口返回结果(Void表示无返回值) */
21     private T result;
22     /** 异常堆栈信息,需要提供调试功能时,将异常加入此堆栈中,便于协调调用方调试,仅作调试用 */
23     private Exception exceptionStack;
24 
25     public RemoteResult() {
26     }
27 
28     public RemoteResult<T> error(String errorMsg) {
29         this.errorMsg = errorMsg;
30         this.isSuccess = false;
31         return this;
32     }
33 
34     public static long getSerialVersionUID() {
35         return serialVersionUID;
36     }
37 
38     public boolean isSuccess() {
39         return isSuccess;
40     }
41 
42     public void setSuccess(boolean success) {
43         isSuccess = success;
44     }
45 
46     public String getErrorMsg() {
47         return errorMsg;
48     }
49 
50     public void setErrorMsg(String errorMsg) {
51         this.errorMsg = errorMsg;
52     }
53 
54     public T getResult() {
55         return result;
56     }
57 
58     public void setResult(T result) {
59         this.result = result;
60     }
61 
62     public Exception getExceptionStack() {
63         return exceptionStack;
64     }
65 
66     public void setExceptionStack(Exception exceptionStack) {
67         this.exceptionStack = exceptionStack;
68     }
69 
70 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用场景
  • 支付方式
  • 代码实现
    • 支付策略接口(PayStrategy)
      • 具体支付方式(AliPayStrategy)
        • 具体支付方式(WxPayStrategy)
          • 具体支付方式(CardPayStrategy)
            • 支付策略上下文(PayStrategyContent)
              • 支付方式枚举(PaymentEnums)
                • 结果集包装类(RemoteResult)
                相关产品与服务
                云直播
                云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档