面向SPI与面向API

目录:

    前言:

    正文:

       什么是API?

       什么是SPI?

       为什么会有SPI?

       如何在我们的应用使用SPI?

前言:

(俗称牢骚,可忽略)

在去年的时候,一直认为研发团队(不是开发团队!)才能写出不改动原来的代码动态的扩展功能或者修改内容,传入不同的接口实现类组合实现热拔插的功能,这种看起来高大上的程序。

造成这种认知的原因很简单:

开发团队一直都是写业务的,而业务是不断地变化的,哪有什么共性可言?况且不加班就好啦,哪有时间想什么接口设计,人家研发团队就是提供组件的,研发就是抽出公共组件服务业务团队的!

不过随着接触一些书籍、朋友和同事,这种认知逐渐被打破,为何呢?看看下文吧!

正文:

什么是API?

API,全称:Application Programming Interface,意思就是应用程序编写接口,结合我们平时的开发翻译一下:来一个需求,首先定义一个接口,根据接口作出实现类,这样一个应用功能就是开发完毕,所以API的意思就是服务端编写好接口,并制定实现类,给第三方使用的一种规范。

以上就是一个简单的API接口的流程

什么是SPI?

SPI,全称:Service Provider Interface,意思就是服务提供程序接口。单纯给出这样一个翻译,可能很多开发的小伙伴看不太懂(如果没有了解过SPI的话),这里简单解释一下:它是定义好抽象类 / 接口来对外提供服务,具体使用哪个实现类,提供服务的服务者并不关心,他所提供的只是一种规范(接口就是定义规范的),举个例子:

public interface LogPlugin {
    public void debug(String condition,Object... param);
    public void info(String condition,Object... param);
    public void warn(String condition,Object... param);
    public void error(String condition,Object... param);
}
 
// Log4j实现
XX01 implements LogPlugin(){}
 
// Slf4j实现
XX02 implements LogPlugin(){}
 
public class UserServiceImpl implements UserService{
    // 测试一个方法使用
    modifierType returnType methodName(LogPlugin logPlugin,ParamterType params...){
        logPlugin.info(condition,Console contents);
    }
}

这里定义了一个插件LogPlugin,在我们应用中并不知情要使用哪个插件来打印我们的日志,具体的实现类是有调用者来给出,这样话,只有再想扩展或者使用其他的日志框架无需修改现有的程序,只需传入不同实现类进行扩展即可。

以上就是一个简单的SPI使用的流程。

为什么会有SPI?

在回答这个问题之前,我想看到这里的小伙伴心中应该有大致的想法了,它可以无需修改原来接口的情况下修改、扩展一些业务内容,所以才有SPI。

这里多唠叨一句吧,不知道小伙伴有没有了解过 设计模式–策略设计模式 其实这里的SPI与策略模式很是雷同(实现上),但并不完全相同,SPI更倾向一种设计理念,策略模式更是一种扩展实现,只是恰巧与SPI的实现有异曲同工之妙而已。如果大家没有了解过该设计模式,有兴趣的朋友可以自行学习一下,本文与至此就点到为止啦!

如何在我们的应用使用SPI?

SPI在上文也大致已经介绍,它是一种面向接口的设计思想,既然是面向接口的,而接口又是一种规范,所以我们第一步就是找出应用的变化部分和不变的部分;

这里以实际用的例子举例:

现在要开发一个结算系统,这个系统结算的类型有两种(未来可能是很多种),一种是按照订单结算,一种是按照活动结算,且结算的规则有实时结算,按天结算等未来也可能继续添加,需求就精简到这里吧。

第一步:找变化的部分和不变的部分。

这个怎么找?我怎么感觉都是变化的部分/都是不变的部分呢?

确实这个是难点,开发过几年,技术实现应该不是大问题,难的就是一眼识破其本质的能力,下面我简单说一条个人的规律吧:一般在产品提出需求的时候会有很多提示,根据产品的提示和自己的经验来寻找这两个部分;看一下上面的需求,结算的类型有两种,那么不变的就是是结算的类型(指的说的是类型,type)和结算的规则(指的是类型,rule),变化的是结算的类型(这里指的是具体实现,注意与前文语义不同,感叹一下汉语语言的精妙哈)和结算的规则(指的是实现类),就这样把变化和不变的部分找出来了,但是这个是只是一个小技巧,具体技巧之后有时间会另起一篇文章讲述,到时候会更新到这里。

第二步:根据不变的不同抽取接口,根据变化的部分抽取实现类

所以我们可以抽取结算类型接口:

public interface SettlementType{
    public <T> T settlement(Message message);
}

public interface SettlementRule{
    public <T> T getSettlementRule(Message message);
}

实现类这里就不写了,就这样,一个简单的SPI就出来了

当然更复杂的,这里时间有限,后续继续更新吧!

转载于:https://my.oschina.net/lovexin/blog/3022635

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值