前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[代码结构设计]根据不同条件使用不同实现类的业务代码设计

[代码结构设计]根据不同条件使用不同实现类的业务代码设计

作者头像
云枭
发布2018-11-08 10:47:49
2.2K0
发布2018-11-08 10:47:49
举报
文章被收录于专栏:fixzd

场景

此时有一个场景,需要设计一个根据不同的状态和条件采用不同的业务处理方式。

这样大家可能不是太理解。举个例子,现在大街小巷上的商户都采用了聚合支付的支付方式,聚合支付也就是商户柜台前放了一个支持支付宝、微信、京东钱包、银联等等的二维码,用户可以通过任意一款支付APP进行支付。

解决思路

思路①

对每个支付渠道进行定义枚举类型

代码语言:javascript
复制
public enum PayWay {
    ALI_PAY,

    WECHAT_PAY;
}

然后在每个对应的service上定义注解,表示对应哪种支付方式

代码语言:javascript
复制
@Pay(PayWay.ALI_PAY)
public class AliPayServiceImpl implements PayService  {}

但是仔细思考后,还是存在一些问题

  1. 如果增加一个支付方式后还需要修改,PayWay这个枚举类型
  2. 在程序中,仍需要根据不同的条件做if else判断PayWay,增加支付方式还是得修改原有的判断逻辑。伪代码如下
代码语言:javascript
复制
if("xxx" == "aliPay"){
    
} else if("xxx" == "wechatPay"){
    
}
//如果增加支付方式还是得增加else if

思路②

在思路①中存在一些问题,首当其冲的就是if else判断问题。先思考一下这个if else的作用是什么?

答:根据思路①描述,这个if else是用来确定采用哪种支付方式。

我们可以将这块代码抽离出来,让对应的业务实现类实现自己的逻辑实现,然后根据返回值true 或者false决定是否过滤掉这个业务实现类。接口定义如下,SupportBean是封装的一个实体

代码语言:javascript
复制
boolean isSupport(SupportBean supportBean);

然后在各个业务实现类都实现自己的isSupport方法,伪代码如下

代码语言:javascript
复制
@Override
public boolean isSupport(SupportBean supportBean) {
    if (supportBean.getType() == "xxx"){
        return true;
    }
    
    return false;
}

设计

注:只提供一个架子

接口定义

Service接口定义,一个业务执行方法execute(参数自行添加),一个isSupport方法(返回true或者false

代码语言:javascript
复制
public interface Service {

    void execute();

    boolean isSupport(SupportBean supportBean);
}

业务实现类

这里execute方法只是在控制台打印字符串。isSupport方法对SupportBean中的supportNum进行取余,判断余数是否等于0,是则返回true。

类似的实现还有两个,这里就不贴出来了。

代码语言:javascript
复制
@Component
public class AServiceImpl implements Service {
    @Override
    public void execute() {
        System.out.println("A execute");
    }

    @Override
    public boolean isSupport(SupportBean supportBean) {
        return supportBean.getSupportNum() % 3 == 0;
    }
}

接下来在定义一个帮助类

帮助类

代码语言:javascript
复制
@Component
public class Helper {

    @Autowired
    private List<Service> services;

    public void execute(SupportBean supportBean){

        Service s = services.stream()
                .filter((service) -> service.isSupport(supportBean))
                .findFirst()//NPE异常
                .orElse(null);


        if (s != null){
            s.execute();
        }
    }
}

通过工具类的execute方法来获取对应的业务实现类执行的结果,以及对传入的参数进行校验处理等。

需要注意的是Lambda表达式的findFirst()会出现NullPointException异常。因为filter对list进行过滤,会存在过滤完list的长度为0,如果此时在调用findFirst则会抛出NullPointException。可以将上面的代码修改为如下代码,这样就可以避免NPE了

代码语言:javascript
复制
Service s = services.stream()
        .filter((service) -> service.isSupport(supportBean))
        .map(Optional::ofNullable)
        .findFirst()
        .flatMap(Function.identity())
        .orElse(null);

测试

添加一个springboot测试类和一个测试方法。

在contextLoads测试中调用帮助类Helper的execute方法

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

    @Autowired
    private Helper Helper;

    @Test
    public void contextLoads() {
        Helper.execute(new SupportBean(3));
    }

}

测试结果

代码语言:javascript
复制
A execute

扩展

在Lambda表达式中是先将业务实现类进行过滤,然后获取第一个业务实现类并执行。

如果此时过滤存在多个业务实现类,而又不能确定优先级,这时需要如何进行扩展呢?

其实很简单,先在Service接口中定义一个getPriority方法

代码语言:javascript
复制
int getPriority();

然后各自的实现类实现对应的getPriority方法

接着修改Lambda表达式即可,在filter后增加sorted方法即可对业务实现类进行排序

代码语言:javascript
复制
Service s = services.stream()
        .filter((service) -> service.isSupport(supportBean))
        .sorted(Comparator.comparing(Service::getPriority))
        .map(Optional::ofNullable)
        .findFirst()
        .flatMap(Function.identity())
        .orElse(null);

总结

整个大体框架基本都搭建完成,如需扩展只需要增加对应的业务实现类,而不用去修改其他类的代码。就连之前设计的枚举都可以不用,可扩展性大大提升。如需使用,只需修改对应的入参和对应的名称即可。 Github地址 如果对你有收获,欢迎star、欢迎fork 如果你也有类似的经验,欢迎加入,一起共建

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-10-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景
  • 解决思路
    • 思路①
      • 思路②
      • 设计
        • 接口定义
          • 业务实现类
            • 帮助类
              • 测试
                • 扩展
                • 总结
                相关产品与服务
                云支付
                云支付(Cloud Pay,CPay)为您提供开放、可靠的聚合收款技术服务和商户管理功能。云支付支持刷卡支付、扫码支付、一码多付多种支付方式。服务商也可使用云支付提供的 SDK 和 HTTPS 接口,将云支付集成进自己的系统中,为商户提供的个性化解决方案。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档