版权声明:本文为博主原创文章,未经博主允许不得转载。
系列教程:Android开发之从零开始系列

大家要是看到有错误的地方或者有啥好的建议,欢迎留言评论

前言:前一段时间公司服务端开发人手不足,而项目急需对接某个平台的短信发送接口,于是我便揽下了这个任务。看了看原来短信发送的工具类代码,发现好几个平台的短信接口方法都堆在一起了,相互之间仅以方法名作为区分,整个工具类好几百行代码,无论是调用相关方法还是维护原有代码,又或者是集成新的短信平台都十分不方便,于是决定一边学习面向对象设计的知识,一边动手重构短信工具类。本期就以市面上几款常见的短信接口为例子,聊一聊这种单一功能(发送短信)但有多种方案(多平台)的工具类的封装过程,希望能对大家项目开发和功能集成有所启发


封装之前的准备工作

在开始动手之前,我们需要考虑怎样去设计这个工具类。首先得明确为什么要进行封装

封装的目的
  • 调用短信工具类的用户尽可能地降低使用成本
  • 后续维护工具类的开发人员能够更加方便地集成其他短信平台和维护原有的代码

按照第一点要求,那么我希望最终调用这个短信工具类时只有一个统一的入口,然后只需要简单地通过一个参数选择短信平台,按该平台要求传入相应的参数即可完成短信发送的操作以及获取返回数据。考虑到各个平台传参的命名都不一样,且可能有自定义的功能扩展,因此决定使用Builder模式去设计工具类入口

再来看第二点要求,如果像原来那样将所有的短信平台接口都放到同一个工具类中,各种解析函数也放在这里面,那维护起来将异常麻烦,还可能会因为集成新的短信平台而引入未知的BUG,因此我们需要将各平台对接代码隔离开来

那么分析了短信工具类如何入手开发之后,根据“自上而下设计,自下而上实现”的思想,我们从各平台短信接口的集成开始一步步实现这个工具类


抽象集成短信平台接口

原有的短信工具类中集成了阿里云、网易云、云信等平台的短信发送接口,它们有的只能使用post进行数据传输,有的post、get两种方式都可以,因此我们进行抽象时需要将这两种传输方式都考虑进来,创建SMSModel抽象类

public abstract class SMSModel {public abstract String post(Map<String, String> map);public abstract String get(Map<String, String> map);
}

以阿里云的短信发送接口为例,新建ALModel继承SMSModel,实现具体的请求过程

/*** 阿里云短信平台*/
public class ALModel extends SMSModel{@Overridepublic String post(Map<String, String> map){//省略具体的代码实现...return result;}@Overridepublic String get(Map<String, String> map) {//因为该平台不支持get方式传输数据,直接返回错误信息即可return "请求失败!该平台不支持get请求";}}

接着按照阿里云短信平台的开发文档,按照入参列表创建SMSParameter,便于用户注入参数

public class SMSParameter {//短信接口平台public static final String SMS_MODEL_AL = "AL";//阿里云短信平台//阿里云短信接口参数,文档:https://help.aliyun.com/document_detail/55284.html?spm=5176.doc55289.6.557.J43llApublic static final String AL_KEYID = "AccessKeyId";public static final String AL_KEYSECRET = "AccessKeySecret";public static final String AL_PHONENUMBERS = "PhoneNumbers";//短信接收号码public static final String AL_SIGNNAME = "SignName";//短信签名public static final String AL_TEMPLATECODE = "TemplateCode";//短信模板IDpublic static final String AL_TEMPLATEPARAM = "TemplateParam";//短信模板变量替换JSON串public static final String AL_SMSUPEXTENDCODE = "SmsUpExtendCode";//上行短信扩展码public static final String AL_OUTID = "OutId";//外部流水扩展字段
}

其他短信平台的集成也是如此,就不多赘述了


实现构建Builder类和中间件Request类

用户在使用我们的封装工具类时,无需知道短信接口具体是如何调用的,隐藏短信接口调用过程可以避免用户调用错误时引发的一系列问题,能够有效地降低用户使用成本。因此我们创建SMSBuilder类用于管理和配置用户调用工具类的传参,实现工具类的自由扩展和构建。创建SMSRequest类用于连接SMSBuilder和SMSModel,起到中间桥梁的作用

先来看SMSBuilder类,我们暂定几个用于初始化工具类的参数,使用枚举(ModelType)限制用户可选用的短信平台,并在setModelType方法中根据用户的选择实例化相应的SMSModel,最后当用户使用build()方法完成工具类初始化时实例化一个SMSRequest执行调用短信接口的操作SMSBuilder代码如下

public abstract class SMSBuilder {public String builderType;//builder类型,分为post和getpublic String modelType;//用户选择的短信平台public Map<String, String> map;//保存短信平台的传参public SMSModel smsModel;/*** 短信平台:* SMS_MODEL_AL(阿里短信平台)*/public enum ModelType{SMS_MODEL_AL}public SMSBuilder() {}public SMSBuilder setModelType(ModelType modelType) {if (modelType != null) {switch (modelType) {case SMS_MODEL_AL:this.modelType = SMSParameter.SMS_MODEL_AL;smsModel = new ALModel();break;default:this.modelType = "";break;}}return this;}public SMSBuilder addMapParams(Map<String, String> map){if(this.map == null){this.map = map;}return this;}public SMSRequest build(){return new SMSRequest(this);}
}

SMSRequest类根据用户利用SMSBuilder初始化的参数执行具体的调用接口操作(toRequest),代码如下

public class SMSRequest {private SMSModel smsModel;private String builderType;private String modelType;private Map<String, String> paramsMap;private String result;private String errorMessage;public SMSRequest(SMSBuilder builder){builderType = builder.builderType;modelType = builder.modelType;paramsMap = builder.map;smsModel = builder.smsModel;result = "";errorMessage = modelType+":"+builderType;if(builder.modelType == null || builder.modelType.equals("")){result = builderType+"请求失败!短信接口类型不能为空";return;}toRequest();}/*** 同步获取返回数据*/public String execute(){return result;}private void toRequest(){if(paramsMap==null){result = errorMessage+"请求失败!map不能为空!";return;}if(builderType.equals("post")){result = smsModel.post(paramsMap);}else if(builderType.equals("get")){result = smsModel.get(paramsMap);}}
}

这里仅以最基础的功能配置为例,若大家需要扩展更多的功能例如超时提醒、群发短信或异步接收回参等可以在此基础上修改


实现面向用户的SMSUtils类

最后再来看下用户直接接触到的类SMSUtils,代码比较简单,这里使用了单例模式实例化SMSUtils,并在其中定义了PostBuilderGetBuilder用于区分post和get请求,具体代码如下

public class SMSUtils {private volatile static SMSUtils mInstance;private SMSUtils(){}private static class SMSUtilsHolder{private static final SMSUtils mInstance = new SMSUtils();}public static SMSUtils getInstance(){return SMSUtilsHolder.mInstance;}public class PostBuilder extends SMSBuilder{public PostBuilder(){this.builderType = "post";}}public class GetBuilder extends SMSBuilder{public GetBuilder(){this.builderType = "get";}}public static PostBuilder post(){return getInstance().new PostBuilder();}public static GetBuilder get(){return getInstance().new GetBuilder();}
}

完成整个工具类的封装后,用户以后调用短信发送接口时只需要像下面示例那样简单写几行代码即可

String result = "";
Map<String, String> map = new HashMap<String, String>();
map.put(SMSParameter.XXX, 参数内容);
...//按照平台要求配置相应参数result = SMSUtils.post()// post():请求类型为post,get():请求类型为get.setModelType(ModelType.SMS_MODEL_AL)// 选择短信平台.addMapParams(map)// 注入参数map.build()// 完成初始化.execute();
System.out.println("result:"+result);

整个工具类的目录结构如下,其中SMSUnitTest用于单元测试,model目录下存放各短信平台的具体实现类,parameter目录用于存放公用的参数常量类,utils目录用于存放某些需要用到的工具类如xml、json解析类等

整个工具类介绍完了,回到我们一开始提出的两点封装目的,我们的工具类是否有效降低了用户的使用成本?我觉得相对于在几百上千行的工具类中查找需要使用的短信接口来说,是的。Builder模式链式结构的初始化过程能让用户调用我们的工具类更加顺手且代码逻辑清晰易读性好。那么是否降低了维护人员的开发成本呢?我们以集成新的短信平台为例,维护人员只需要在model包下创建新的平台实现类,然后在SMSBuilder中配置相应的参数即可,大大降低了工具类的耦合度,也减少了多人开发造成冲突的可能性。若某个平台的对接出现BUG,仅需要在相应的实现类中DEBUG即可

本期博客到这里就结束了,由于我个人能力有限,有些地方肯定做得还不够好,若大家有什么建议欢迎留言指出,不断地写BUG再修复BUG才能学到更多的东西,共勉~

Android项目实践——短信发送接口的封装与设计相关推荐

  1. SpringBoot项目实现短信发送接口开发

    一. 短信接口实现 描述:请求第三方短信接口平台(而第三方短信平台的接口请求是webservice方式实现的),此时我们要测试接口是否通,要用的工具SoapUI测试工具, 不能用PostMan,即使用 ...

  2. android不调用系统发送短信,android之两种方式调用短信发送接口

    释放双眼,带上耳机,听听看~! 相信很多程序员在开发程序的时候都会遇到短信调用端口的情况,今天是技术狗小编为大家带来的关于android之两种方式调用短信发送接口,希望对你学习这方面知识有帮助! an ...

  3. IDM短信发送接口设计说明

    对于大多数企业而言,信息化建设的主要目的是通过信息化驱动业务,实现业务升级与优化,主要有三种体现形式:建设业务系统,实现业务流程标准化.便捷化:整合业务系统和数据,形成数据资产:业务数据呈现,直观展现 ...

  4. 阿里云短信发送接口直接HTTP请求调用

    最新一个个性化项目,客户要求使用阿里云短信发送接口. 但是实在不想引入阿里云的SDK,就自己生成签名,拼接URL实现,  其实用他们的SDK最终也是一哥GET请求进行调用,归根接底还是HTTP请求. ...

  5. django框架中嵌入容联云sdk实现短信发送接口

    1.注册容联云账号,主要是为了获取如下参数 添加测试手机号 2.关于sdk和用法可参考Demo示例,demo下载在最上面Demo下载 3.在自己的项目中导入需用到的模块 4.更改配置为自己申请的应用配 ...

  6. java短信发送接口代码示例demo分享

    适用类型:适用于各类办公系统.ERP.CRM.电子商务平台的插件(如网站app短信验证码.群发短信会议通知.会员/客户关系交流.订单生成通知.发货通知.日程提醒.催费通知等等) 接 口特 点: 绿色短 ...

  7. JAVA发送手机短信,httpclient短信发送接口示例(java)

    httpclient短信发送接口示例(java),可用于直接用电脑发送短信,可根据实际情况,与联通移动公司洽谈接口,完成网上发送短信功能,如需jar包,可向联通移动公司项目部沟通. package c ...

  8. 创蓝253云通讯 paas 短信发送接口和定义说明

    一.demo: #include <arpa/inet.h> #include <assert.h> #include <errno.h> #include < ...

  9. 短信发送接口被恶意访问的网络攻击事件(二)肉搏战-阻止恶意请求

    前言 承接前文<短信发送接口被恶意访问的网络攻击事件(一)紧张的遭遇战险胜>,在解决了短信发送的问题后,长长地舒了口气,也就各忙各的事情去了,本以为应该是个完美的收场,哪知道只是泥泞道路的 ...

最新文章

  1. 在ROS使用奥比中光Orbbec Astra Pro
  2. 真正的中台价值,「炒作」之后才被看见
  3. 干货 | 蚂蚁金服是如何实现经典服务化架构往 Service Mesh 方向的演进的?
  4. Android组件的通讯-Intent
  5. 【线性规划与网络流24题】汽车加油行驶问题 分层图
  6. 【MFC系列2】Win32项目转换为MFC项目
  7. yii2 跨域请求配置_如何在SpringBoot应用中实现跨域访问资源和消息通信?
  8. 聊聊汽车智能化时代的ASIL
  9. 达梦数据库,查看表空间使用情况
  10. java安卓开发改变图片大小_Android代码中动态设置图片的大小(自动缩放),位置...
  11. dbv数据库乱码_使用DBV进行数据库版本控制
  12. 市面上比较好用的钣金展开软件都有哪些?
  13. 用python画 pareto front
  14. 微信小程序|icon列表跳转不同界面
  15. 通过短信网关发送Wappush消息
  16. linux挂nas盘步骤,linux下需要将nas盘挂
  17. QUICK PCB抄板教程(无网络编号)
  18. c语言中public 用法,深入理解C++中public、protected及private用法
  19. JavaScript(JS) string.italics( )
  20. 李开复写给中国大学生的七封信【3/7】

热门文章

  1. nologging何时能减少redo
  2. [Python]五分钟理解元类(Metaclasses)
  3. 淘宝双十二/1212任务自动助手脚本,自动完成任务领取淘金币奖励
  4. 怎么打开SQL SERVER 2012的配置管理器
  5. 哪些成员函数不能被继承
  6. 用Docker安装Redmine
  7. 百度云盘幺蛾子多,我们不用他难道还不行了吗?
  8. excel表格部分经常引用的几个简单的公式【excel使用技能】
  9. 计算机课程标准的内容,《计算机》课程标准2015619.doc
  10. 【先锋】犀思云张雄国:帮助企业更好地过渡到互联网时代