「设计模式」通过购买网易云音乐会员了解策略模式

我们在购买网易云音乐会员的时候,支付页有两个选项,分别是支付宝支付和微信支付,这个后台结算进行开发的时候,如果要提高程序的可维护性,那么大概率会使用标题所提到的策略模式。

1.模式定义

这里就直接给出GoF的官方定义吧,后续我们围绕这个定义展开:

Define a family of algorithms, encapsulate each one, and make them interchangeable.

定义一个算法家族,分别封装起来,使得它们之间可以互相变换。

可以看到,这个定义就非常吻合我们的这个支付场景了,网易云可以内容实现了支付宝支付策略,微信支付策略,用户根据情况选择其中的一种支付方式,便是选择其中的一种支付策略。

2.模式结构

这里是常规的策略模式的模式结构图

https://refactoringguru.cn/design-patterns/strategy

实际开发我们会考虑各种优化,以及使用各种开发框架如Spring,会和结构图中有所区别:

3.模式实现

本着了解的模式为先的原则,所以代码结构力求简单明了。同时贴近实际生产,如使用了Spring框架等。

3.1.定义支付枚举

后续新增支付方式,记得这里维护下

package com.example.designpattern.strategy.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 支付策略
 *
 * @author hongcunlin
 */
@Getter
@AllArgsConstructor
public enum PayEnums {
    /**
     * 支付宝支付
     */
    ALI(1, "支付宝支付"),

    /**
     * 微信支付
     */
    WE_CHAT(2, "微信支付");

    /**
     * 支付类型码
     */
    private final Integer code;

    /**
     * 支付类型名称
     */
    private final String name;
}

3.2.定义支付策略

package com.example.designpattern.strategy.paystrategy;

/**
 * 支付策略
 *
 * @author hongcunlin
 */
public interface PayStrategy {
    /**
     * 支付
     */
    void pay();
}

3.3.实现支付宝支付、微信支付策略

package com.example.designpattern.strategy.paystrategy.impl;

import com.example.designpattern.strategy.paystrategy.PayStrategy;
import org.springframework.stereotype.Service;

/**
 * 支付宝支付
 *
 * @author hongcunlin
 */
@Service
public class AliPayStrategy implements PayStrategy {
    @Override
    public void pay() {
        System.out.println("支付宝支付");
    }
}
package com.example.designpattern.strategy.paystrategy.impl;

import com.example.designpattern.strategy.paystrategy.PayStrategy;
import org.springframework.stereotype.Service;

/**
 * 微信支付
 *
 * @author hongcunlin
 */
@Service
public class WeChatPayStrategy implements PayStrategy {
    @Override
    public void pay() {
        System.out.println("微信支付");
    }
}

另外实际开发中,通常会有一个默认的实现用于兜底。

package com.example.designpattern.strategy.paystrategy.impl;

import com.example.designpattern.strategy.paystrategy.PayStrategy;
import org.springframework.stereotype.Service;

/**
 * 默认支付
 *
 * @author hongcunlin
 */
@Service
public class DefaultPayStrategy implements PayStrategy {
    @Override
    public void pay() {
        System.out.println("支付失败");
    }
}

3.4.定义支付上下文

这类注入了各大策略实现

package com.example.designpattern.strategy.context;

import com.example.designpattern.strategy.enums.PayEnums;
import com.example.designpattern.strategy.paystrategy.PayStrategy;
import com.example.designpattern.strategy.paystrategy.impl.AliPayStrategy;
import com.example.designpattern.strategy.paystrategy.impl.DefaultPayStrategy;
import com.example.designpattern.strategy.paystrategy.impl.WeChatPayStrategy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 支付上下文
 *
 * @author hongcunlin
 */
@Component
public class PayContext {
    /**
     * 支付策略
     */
    private PayStrategy payStrategy;

    /**
     * 默认支付
     */
    @Resource
    private DefaultPayStrategy defaultPayStrategy;

    /**
     * 支付宝支付
     */
    @Resource
    private AliPayStrategy aliPayStrategy;

    /**
     * 微信支付
     */
    @Resource
    private WeChatPayStrategy weChatPayStrategy;

    /**
     * 设置支付策略
     *
     * @param code 支付策略码
     */
    public void setPayStrategy(Integer code) {
        if (PayEnums.ALI.getCode().equals(code)) {
            payStrategy = aliPayStrategy;
        } else if (PayEnums.WE_CHAT.getCode().equals(code)) {
            payStrategy = weChatPayStrategy;
        } else {
            payStrategy = defaultPayStrategy;
        }
    }

    /**
     * 执行策略
     */
    public void execute() {
        if (null == payStrategy) {
            throw new RuntimeException("未设置支付方式");
        }
        payStrategy.pay();
    }
}

3.5.测试

我们注入支付上下文PayContext,通过枚举指定支付的方式,执行PayContext的execute方法完成支付。

package com.example.designpattern.strategy;

import com.example.designpattern.strategy.context.PayContext;
import com.example.designpattern.strategy.enums.PayEnums;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@SpringBootTest
public class DesignPatternTest {
    /**
     * 支付上下文
     */
    @Resource
    private PayContext payContext;

    /**
     * 测试
     */
    @Test
    public void test() {
        payContext.setPayStrategy(PayEnums.ALI.getCode());
        payContext.execute();
    }
}

这是运行结果,可以看到,是符合我们的预期的

4.模式优点

最后来简单聊聊使用了策略模式后的有点,主要体现在如果后面网易云音乐会员支持方式,新增了京东支付、抖音支付等支付方式,我们可以通过新增相应的京东支付策略、抖音支付策略即可,原有的主流程无需改变,即:

每新增一个策略,只需要新增策略的实现即可,无需改动原有的流程。

后续有空,我们接着依据现实生活,聊聊设计模式中的其他设计模式。

展开阅读全文

页面更新:2024-02-02

标签:网易   策略   模式   可维护性   上下文   框架   定义   类型   结构   方式   会员   音乐

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top