02 设计模式之策略模式

举报
陈皮的JavaLib 发表于 2021/08/02 22:52:27 2021/08/02
【摘要】 对于一系列的算法,将具体的算法实现从具体的业务中独立出来,将它们封装成一个个单独的算法类,这些算法是平等的,算法之间可相互替换,并且可独立于使用算法的客户端而变化。

我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复【资料】,即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板。

1 前言

对于某些在线商城,用户买东西付款时可以选择不同的电子支付方式,例如支付宝,微信,银联等等。对于用户选择不同的支付方式,后台支付模块可以简单实现如下:

package com.chenpi.strategy;

/**
 * @Description 策略模式
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class ChenPiClient {

  public static void main(String[] args) {
    pay(78.5, "Alipay");
  }

  public static void pay(double money, String payType) {
    if ("Alipay".equals(payType)) {
      System.out.println("使用支付宝支付金额:" + money);
    } else if ("WeChatPay".equals(payType)) {
      System.out.println("使用微信支付金额:" + money);
    } else if ("UnionPay".equals(payType)) {
      System.out.println("使用银联支付金额:" + money);
    }
  }
}

// 输出结果
使用支付宝支付金额:78.5

以上实现方案在业务比较简单,支付方式数量少的情况下还勉强可接受。如果在支付业务比较复杂,支付方式数量多的情况下,那方法 pay 会变得庞大臃肿,难以维护。

即使可以将每个条件分支执行的内容划分到一个个单独的方法中,那随着不同支付业务复杂化,支付方式的增多,也会导致这个类变得庞大,难以维护,也违背了类单一原则,开闭原则。

2 策略模式(Strategy)

策略模式就能很好地解决以上问题。那何为策略模式呢?

对于一系列的算法,将具体的算法实现从具体的业务中独立出来,将它们封装成一个个单独的算法类,这些算法是平等的,算法之间可相互替换,并且可独立于使用算法的客户端而变化。

策略模式主要用来解决如何组织,调用一系列算法,从而让程序结构更加灵活,可维护和可扩展。它并不关心如何去实现算法。

策略模式的结构一般由三部分组成:

  • Strategy:策略接口,定义了一系列算法接口。
  • ConcreteStrategy:具体的策略实现类,负责具体的算法实现。
  • Context:上下文,持有具体的策略接口实现类,并根据客户端的算法选择,负责与具体策略实现类交互,执行相应的算法。

3 应用

对于文章开头提到的支付问题,不同的支付业务对应不同的算法,而使用这些算法的就是客户端,它们之间是耦合在一起的。所以我们需要将不同支付(算法实现)抽离出来,封装成一个个单独的支付类(算法类),同时定义一个算法公共接口,不同算法实现类都实现此接口。

以后要是增加新的支付方式,只需要增加一个新的算法实现类即可,也不会对其他算法实现类造成影响,达到了可扩展和可维护的效果。

首先定义策略接口,所有具体的策略实现类都要实现它。

package com.chenpi.strategy;

/**
 * @Description 策略接口
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public interface PayStrategy {

  void pay(double money);
}

然后定义不同的具体策略实现类,并且实现策略接口。

package com.chenpi.strategy;

/**
 * @Description 支付宝支付策略实现类
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class AliPayStrategy implements PayStrategy {

  @Override
  public void pay(double money) {
    System.out.println("使用支付宝支付金额:" + money);
  }
}
package com.chenpi.strategy;

/**
 * @Description 微信支付策略实现类
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class WeChatPayStrategy implements PayStrategy {

  @Override
  public void pay(double money) {
    System.out.println("使用微信支付金额:" + money);
  }
}
package com.chenpi.strategy;

/**
 * @Description 银联支付策略实现类
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class UnionPayStrategy implements PayStrategy {

  @Override
  public void pay(double money) {
    System.out.println("使用银联支付金额:" + money);
  }
}

在策略模式中,为了让算法独立于使用算法的客户端,引入上下文对象,它持有具体的算法实现类,根据客户端选择具体的算法后,执行对应的具体算法。如此一来,算法的变化而不影响到客户端,客户端通过上下文对象还可以动态切换不同的算法。

package com.chenpi.strategy;

/**
 * @Description 上下文对象
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class PayContext {

  // 持有具体的策略实现类,一般由客户端决定设置
  private PayStrategy payStrategy;

  // 构造方法,接受一个具体的策略实现类
  public PayContext(PayStrategy payStrategy) {
    this.payStrategy = payStrategy;
  }

  // 暴露给客户端调用的方法,实现调用具体策略类的方法来实现
  public void pay(double money) {
    payStrategy.pay(money);
  }
}

最后客户端就可以进行调用了。

package com.chenpi.strategy;

/**
 * @Description 策略模式
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class ChenPiClient {

  public static void main(String[] args) {
    new PayContext(new AliPayStrategy()).pay(78.5);
  }
}

//输出结果
使用支付宝支付金额:78.5

如果此时增加一种新的支付方式,信用卡支付,那么只需要新增一个策略实现类即可。

package com.chenpi.strategy;

/**
 * @Description 信用卡支付策略实现类
 * @Author 陈皮
 * @Date 2021/7/31
 * @Version 1.0
 */
public class CreditCardPayStrategy implements PayStrategy {

  @Override
  public void pay(double money) {
    System.out.println("使用信用卡支付金额:" + money);
  }
}

支付模块的策略模式的结构关系如下图所示。

4 总结

策略模式能将不同算法从业务处理中独立出来,实现了可维护性,可扩展性。但是策略模式也有缺点,例如编写的类的数目增加了,客户端调用需要知道每一种策略,才能选择合适的策略实现类,其实也变相暴露了策略的具体实现。

只有由客户端来选择具体的策略算法的情况下,客户端才需要知道所有的具体策略,当然上下文也可以结合工厂方法模式,接收客户端传进来的标识,创建相应的具体策略类。

还有另一种具体策略的选择,不是由客户端决定,而是由上下文来选择具体的策略算法。选择策略例如,默认的策略顺序(一种策略出现问题,换执行下一个策略),读取环境变量的值决定使用哪种策略,读取数据库数据等。


本次分享到此结束啦~~

如果觉得文章对你有帮助,点赞、收藏、关注、评论,您的支持就是我创作最大的动力!

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。