1、为什么我们要使用设计模式;
    使用设计模式可以重构整体架构代码,提高代码复用性、扩展性。

    2、设计模式六大原则;

    开闭原则:
    开闭原则就是对扩展开放,对修改关闭,在程序需要扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。

    里氏替换原则:
    里氏替换原则是面向对象设计的基本原则之一,里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现。里氏替换原则是对开闭原则的补充,实现开闭原则的关键步骤就是抽象化。

    依赖倒转原则:
    这是开闭原则的基础,直接对接口编程,以来抽象不依赖于具 体。

    接口隔离原则:
    使用多个隔离的接口比使用单个接口要好

    迪米特法则(最少知道原则):
    一个实体应当尽量少的与其他实体之间发生相互作用,使得系统 功能模块相对独立。

    合成复用原则:
    原则是尽量使用合成/聚合的方式,而不是使用继承。

    2、策略者模式
    策略者模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多重If判断的问题。

    3、使用策略者模式有以下几个角色
    环境角色(Context):持有一个Strategy引用;
    抽象策略角色(Strategy):这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有具体类略类所需的接口;
    具体策略角色(ConcreteStrategy):包装了相关的算法或行为.

    4、策略者模式的使用场景
    比如:搭建聚合支付平台,这个时候需要调用很多第三方支付接口,支付宝、微信、银联、小米等等支付接口。
    如果通过以下这种if判断来实现,如果以后想要增加一种支付方式,后期的维护性就会非常差。

    1. public String toPayHtml2(String payCode){
    2. if(payCode.equals("ali_pay")){
    3. return "调用支付宝接口...";
    4. }
    5. if(payCode.equals("xiaomi_pay")){
    6. return "调用小米支付接口";
    7. }
    8. if(payCode.equals("yinlian_pay")){
    9. return "调用银联支付接口...";
    10. }
    11. return "未找到该接口...";
    12. }


    策略者模式架构图
    tt.jpg.png
    以下就架构图上的每一角色写代码

    抽象角色:

    1. public interface PayStrategy {
    2. /**
    3. * 共同算法实现骨架
    4. * @return
    5. */
    6. public String toPayHtml();
    7. }

    具体实现角色:

    1. @Component
    2. public class AliPayStrategy implements PayStrategy {
    3. public String toPayHtml() {
    4. return "调用支付宝支付接口";
    5. }
    6. }
    7. @Component
    8. public class XiaoMiPayStrategy implements PayStrategy {
    9. public String toPayHtml() {
    10. return "调用小米支付接口";
    11. }

    环境角色:

    1. @RestController
    2. public class PayContextService {
    3. @Autowired
    4. private PaymentChannelMapper paymentChannelMapper;
    5. @Autowired
    6. private SpringUtils springUtils;
    7. @RequestMapping("/toPayHtml")
    8. public String toPayHtml(String payCode){
    9. // 1.验证参数
    10. if(StringUtils.isEmpty(payCode)){
    11. return "payCode不能为空!";
    12. }
    13. // 2.使用PayCode查询
    14. PaymentChannelEntity paymentChannel = paymentChannelMapper.getPaymentChannel(payCode);
    15. if(paymentChannel==null){
    16. return "该渠道为空...";
    17. }
    18. // 3.获取策略执行的beanid
    19. String strategyBeanId = paymentChannel.getStrategyBeanId();
    20. // 4.使用strategyBeanId获取对应spring容器bean信息
    21. PayStrategy payStrategy = springUtils.getBean(strategyBeanId, PayStrategy.class);
    22. // 5.执行具体策略算法
    23. return payStrategy.toPayHtml();
    24. }
    25. }

    这个里边有用到了一个工具SpringUtils

    1. @Component
    2. public class SpringUtils implements ApplicationContextAware {
    3. private static ApplicationContext applicationContext;
    4. @Override
    5. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    6. this.applicationContext = applicationContext;
    7. }
    8. //获取applicationContext
    9. public static ApplicationContext getApplicationContext() {
    10. return applicationContext;
    11. }
    12. //通过name获取 Bean.
    13. public static Object getBean(String name){
    14. return getApplicationContext().getBean(name);
    15. }
    16. //通过class获取Bean.
    17. public static <T> T getBean(Class<T> clazz){
    18. return getApplicationContext().getBean(clazz);
    19. }
    20. //通过name,以及Clazz返回指定的Bean
    21. public static <T> T getBean(String name,Class<T> clazz){
    22. return getApplicationContext().getBean(name, clazz);
    23. }
    24. }

    其实这个工具也可以替换为我们自己些一个本地缓存Map(id,实体)

    还有就是为什么要查询数据库:是因为要动态维护前端传来type与我们具体策略类的映射关系。