使用场景
公司最近在做直播功能, 底层原来有一套直播 API, 现在新增一套网宿直播 API.
考虑以后的扩展性, 需要将两套 API 进行统一管理. 现在以网上的支付方式演示我对策略模式的理解.
支付方式
我们知道网上有很多支付方式. 支付宝, 微信, 银行卡, 花呗...
我们以三种支付方式进行演示.
策略模式的组成有三部分
环境类 (Context): 用一个 ConcreteStrategy 对象来配置. 维护一个对 Strategy 对象的引用.
可定义一个接口来让 Strategy 访问它的数据, 在上一个例子中相当于 Staff.
抽象策略类 (Strategy): 定义所有支持的算法的公共接口. Context 使用这个接口来调用某 ConcreteStrategy 定义的算法,
在上一个例子中相当于 GrantReward.
具体策略类 (ConcreteStrategy): 以 Strategy 接口实现某具体算法, 在上一个例子中相当于 GrantSuger,GrantMoonCake,GrantNone.
支付方式的组成也有三部分
支付策略接口 (PayStrategy): 定义支付方式
具体支付方式 (AliPayStrategy,WxPayStrategy,CardPayStrategy): 具体的支付算法
支付策略上下文 (PayStrategyContent): 管理所有支付方式的引用, 并根据用户选择引用对应的支付方式.
代码实现
支付策略接口 (PayStrategy)
- /**
- * 支付策略接口
- * @author JinXing
- * @date 2019/7/12 13:58
- */
- public interface PayStrategy {
- /**
- *
- * 选择支付方式
- * 支付宝
- * 微信
- * 银行卡
- * @return RemoteResult
- */
- RemoteResult<String> toPayhtml();
- }
具体支付方式 (AliPayStrategy)
- /**
- * 阿里 pay
- * @author JinXing
- * @date 2019/7/12 14:36
- */
- @Service
- public class AliPayStrategy implements PayStrategy {
- @Override
- public RemoteResult<String> toPayHtml() {
- System.out.println("现在采用的支付方式为: 支付宝支付......");
- return null;
- }
- }
具体支付方式 (WxPayStrategy)
- /**
- * 微信支付
- * @author JinXing
- * @date 2019/7/12 14:36
- */
- @Service
- public class WxPayStrategy implements PayStrategy {
- @Override
- public RemoteResult<String> toPayHtml() {
- System.out.println("现在采用的支付方式为: 微信支付......");
- return null;
- }
- }
具体支付方式 (CardPayStrategy)
- /**
- * 银行卡支付
- * @author JinXing
- * @date 2019/7/12 14:36
- */
- @Service
- public class CardPayStrategy implements PayStrategy {
- @Override
- public RemoteResult<String> toPayHtml() {
- System.out.println("现在采用的支付方式为: 银行卡支付......");
- return null;
- }
- }
支付策略上下文 (PayStrategyContent)
- /**
- * 支付策略上下文
- * @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)
**
* 支付方式枚举对象
* 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)
- /**
- * <pre>
- * 远程接口值对象, 此对象使用说明
- * 使用时, 判断 isSuccess 返回值, true 表示业务成功, false 表示接口调用失败
- * errorCode, 用于判断失败原因 (非系统错误), 系统预设错误码, 用负数表示:-1 表示参数不合法, 用户自定义错误码使用正数表示, 0 表示无错误
- * </pre>
- *
- * @author jx
- * @param <T>
- */
- public class RemoteResult<T> implements Serializable {
- private static final long serialVersionUID = 1L;
- /** 接口调用是否成功 (业务), 系统错误, 业务失败都将返回 false */
- private boolean isSuccess = true;
- /** 自定义错误信息, 发生可处理错误时, 返回自定义信息 */
- private String errorMsg = "ok";
- /** 接口返回结果 (Void 表示无返回值) */
- private T result;
- /** 异常堆栈信息, 需要提供调试功能时, 将异常加入此堆栈中, 便于协调调用方调试, 仅作调试用 */
- private Exception exceptionStack;
- public RemoteResult() {
- }
- public RemoteResult<T> error(String errorMsg) {
- this.errorMsg = errorMsg;
- this.isSuccess = false;
- return this;
- }
- public static long getSerialVersionUID() {
- return serialVersionUID;
- }
- public boolean isSuccess() {
- return isSuccess;
- }
- public void setSuccess(boolean success) {
- isSuccess = success;
- }
- public String getErrorMsg() {
- return errorMsg;
- }
- public void setErrorMsg(String errorMsg) {
- this.errorMsg = errorMsg;
- }
- public T getResult() {
- return result;
- }
- public void setResult(T result) {
- this.result = result;
- }
- public Exception getExceptionStack() {
- return exceptionStack;
- }
- public void setExceptionStack(Exception exceptionStack) {
- this.exceptionStack = exceptionStack;
- }
- }
来源: https://www.cnblogs.com/IT-study/p/11195260.html