此时有一个场景,须要设计一个根据不一样的状态和条件采用不一样的业务处理方式。java
这样你们可能不是太理解。举个例子,如今大街小巷上的商户都采用了聚合支付的支付方式,聚合支付也就是商户柜台前放了一个支持支付宝、微信、京东钱包、银联等等的二维码,用户能够经过任意一款支付APP进行支付。git
对每一个支付渠道进行定义枚举类型github
public enum PayWay { ALI_PAY, WECHAT_PAY; }
而后在每一个对应的service上定义注解,表示对应哪一种支付方式spring
@Pay(PayWay.ALI_PAY) public class AliPayServiceImpl implements PayService {}
可是仔细思考后,仍是存在一些问题springboot
PayWay
这个枚举类型if else
判断PayWay
,增长支付方式仍是得修改原有的判断逻辑。伪代码以下if("xxx" == "aliPay"){ } else if("xxx" == "wechatPay"){ } //若是增长支付方式仍是得增长else if
在思路①中存在一些问题,首当其冲的就是if else
判断问题。先思考一下这个if else
的做用是什么?微信
答:根据思路①描述,这个if else
是用来肯定采用哪一种支付方式。框架
咱们能够将这块代码抽离出来,让对应的业务实现类实现本身的逻辑实现,而后根据返回值true
或者false
决定是否过滤掉这个业务实现类。接口定义以下,SupportBean
是封装的一个实体ide
boolean isSupport(SupportBean supportBean);
而后在各个业务实现类都实现本身的isSupport方法,伪代码以下工具
@Override public boolean isSupport(SupportBean supportBean) { if (supportBean.getType() == "xxx"){ return true; } return false; }
注:只提供一个架子测试
Service接口定义,一个业务执行方法execute(参数自行添加),一个isSupport方法(返回true
或者false
)
public interface Service { void execute(); boolean isSupport(SupportBean supportBean); }
这里execute方法只是在控制台打印字符串。isSupport方法对SupportBean中的supportNum进行取余,判断余数是否等于0,是则返回true。
相似的实现还有两个,这里就不贴出来了。
@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; } }
接下来在定义一个帮助类
@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了
Service s = services.stream() .filter((service) -> service.isSupport(supportBean)) .map(Optional::ofNullable) .findFirst() .flatMap(Function.identity()) .orElse(null);
添加一个springboot测试类和一个测试方法。
在contextLoads测试中调用帮助类Helper的execute方法
@RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTests { @Autowired private Helper Helper; @Test public void contextLoads() { Helper.execute(new SupportBean(3)); } }
测试结果
A execute
在Lambda表达式中是先将业务实现类进行过滤,而后获取第一个业务实现类并执行。
若是此时过滤存在多个业务实现类,而又不能肯定优先级,这时须要如何进行扩展呢?
其实很简单,先在Service接口中定义一个getPriority
方法
int getPriority();
而后各自的实现类实现对应的getPriority
方法
接着修改Lambda表达式便可,在filter后增长sorted方法便可对业务实现类进行排序
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 若是你也有相似的经验,欢迎加入,一块儿共建