对于有多种可替代解决方案的业务逻辑,提供一种快速更换的思路
2016-12-23 12:24
435 查看
转载自:https://v1sk.github.io/archives/
举几个例子说明:
客户端的http请求操作,可以实现的方案有Retrofix、OkHttp、Volley等;
客户端的数据库存储方案可以为Realm、greenDao、OrmLite等;
图片加载的方案可以是Fresco、Glide、Picasso、UIL等。
先来描述一下需求,比如说,目前正在用的http请求是Volley,现在发现使用OkHttp来封装一套会更好。又比方说,目前正在用的数据存储方案是OrmLite,现在使用greenDao或者Realm会更好,在类似这些情况下,如何做到不修改Activity/Fragment/Presenter代码的情况下,把Volley的http请求实现更换成Okhttp的实现,把OrmLite更换成greenDao或者Realm?
解决问题的关键词:设计模式中的——工厂方法模式。
本质:利用接口进行解耦。
说到这里,可能很多有经验的朋友已经会心一笑,是的,老实说这篇文章可能对老司机没有太大的意义,但是如果看到这里还是心存疑问,或者你不知道什么是工厂方法模式,也不知道如何使用接口解耦什么的,没关系,请继续往下看。
下面,我们就用Volley更换到OkHttp这个例子来说明一下如何做到不修改Activity/Fragment/Presenter的代码情况下,更快地更换业务逻辑实现的代码。
在开始之前先来思考一下上述所说“可替代解决方案”的含义,为何这些方案是可替代的?是因为它们具有相同的共性,它们所要解决的问题是相同的,比如说http请求框架,无论是Volley/OkHttp/Retrofix,它们所要实现的都是http请求中的get/post/put/delete这些方法,数据库存储框架中无论是Realm/greenDao/OrmLite,它们要实现的都是增删改查这些方法。
“博主你别再瞎逼逼,赶紧说重点…”
我:dalao我错了,下面说重点…
先来概括一下我们的实现思路:
把http请求框架的共性方法抽取到接口中,我们把这个接口称为“请求接口”;
创建一个用于返回请求结果的接口,我们把这个接口称为“回调接口”;
分别用Volley和OkHttp实现“请求接口”;
创建一个类来返回上述接口的对象,我们把这个类叫做“工厂”类;
在Activity/Fragment/Presenter中,使用“工厂”返回的这个接口对象调用get/post/put/delete方法,并在“回调接口”中得到请求结果。
本文完整代码https://github.com/V1sk/HttpRequestExample,可以先clone到本地再看文章,为了方便阅读,下文中的代码将省略非重点部分。
上面的IRequestManager接口中用到的请求结果回调接口——IRequestCallback
至此,我们已经把数据请求的接口,以及数据返回的接口都定义好了,整理一下思绪
首先我们搞清楚http请求,有哪些方法,需要有哪些参数——IRequestManager;
数据返回会有什么情况?——IRequestCallback;
VolleyRequestManager实现了IRequestManager接口,到这里我想你也看出来可以使用VolleyRequestManager来进行get/post/put/delete操作了,是的,已经可以用于请求操作,但是我们先不这样做,原因请继续往下看Step3。
到这里,请容许我再逼逼一下,为什么要用这种方法来返回对象,而不直接在Activity/Fragment/Presenter中创建VolleyRequestManager对象来进行操作?如果直接在Activity/Fragment/Presenter中使用VolleyRequestManager来创建对象,你的代码就依赖了VolleyRequestManager,这种情况下,如果要更换成OkHttp,岂不是要把代码中所有的VolleyRequestManager对象也更换成OkHttp的请求对象?再试想一下,如果你有很多个Activity/Fragment/Presenter使用了VolleyRequestManager对象,你是不是要每个地方都更换一遍?
使用RequestFactory的方式在Activity/Fragment/Presenter中创建对象,代码只依赖了IRequestManager这个接口,这就是使用接口进行解耦的关键点,无论在什么地方使用了这个接口,当要更换实现的时候,只需要修改RequestFactory中return的实现类就可以了。
注意我们创建请求对象的代码,这里没有出现具体的实现类:
IRequestManager requestManager = RequestFactory.getRequestManager();
1)先用OkHttp来实现IRequestManager这个接口.
2) 使用OkHttp更换Volley
现在我们用OkHttp的请求方式也实现了一套get/post/put/delete的请求方法,此时只要修改Step3中,返回的对象为OkHttpRequestManager对象,就已经完成了我们整个http请求框架的更换,此时,你可以完全移除Volley的引用以及代码,而不会对程序有任何影响。
对于有多种可替代解决方案的业务逻辑,我的解耦思路是这样的:
抽取它们的共性方法到接口中;
使用自己选择的实现方案去实现;
使用“工厂”类把具体实现转换成抽象接口,并返回抽象接口对象;
Activity/Fragment/Presenter中,使用“工厂”中返回的接口进行操作,而不要依赖于其实现类。
要更换方案的时候,只需要修改“工厂”中返回的实现类。
这篇文章只是提供一种解耦思想,而不是“如何封装http请求框架”的教程,也不是讨论“哪个http请求框架好用”的文章,当然,你完全可以用这种方法进行http请求的封装。然后,这篇文章是博主的第一篇文章,可能写得不是很好,欢迎大家提出宝贵意见,一直都想写blog,可惜除了工作,还要学习,没有太充裕的时间,现在好了,公司忽然告诉我们说破产了,实在是惊魂未定,听说写作可以让人平静,于是我开始尝试写blog这个一直没有付诸行动的小心愿,写写文章压压惊。
什么是“有多种可替代解决方案的业务逻辑”?
举几个例子说明:客户端的http请求操作,可以实现的方案有Retrofix、OkHttp、Volley等;
客户端的数据库存储方案可以为Realm、greenDao、OrmLite等;
图片加载的方案可以是Fresco、Glide、Picasso、UIL等。
如何快速替换?
先来描述一下需求,比如说,目前正在用的http请求是Volley,现在发现使用OkHttp来封装一套会更好。又比方说,目前正在用的数据存储方案是OrmLite,现在使用greenDao或者Realm会更好,在类似这些情况下,如何做到不修改Activity/Fragment/Presenter代码的情况下,把Volley的http请求实现更换成Okhttp的实现,把OrmLite更换成greenDao或者Realm?解决问题的关键词:设计模式中的——工厂方法模式。
本质:利用接口进行解耦。
说到这里,可能很多有经验的朋友已经会心一笑,是的,老实说这篇文章可能对老司机没有太大的意义,但是如果看到这里还是心存疑问,或者你不知道什么是工厂方法模式,也不知道如何使用接口解耦什么的,没关系,请继续往下看。
Talk
is cheap, show me the code.
下面,我们就用Volley更换到OkHttp这个例子来说明一下如何做到不修改Activity/Fragment/Presenter的代码情况下,更快地更换业务逻辑实现的代码。在开始之前先来思考一下上述所说“可替代解决方案”的含义,为何这些方案是可替代的?是因为它们具有相同的共性,它们所要解决的问题是相同的,比如说http请求框架,无论是Volley/OkHttp/Retrofix,它们所要实现的都是http请求中的get/post/put/delete这些方法,数据库存储框架中无论是Realm/greenDao/OrmLite,它们要实现的都是增删改查这些方法。
“博主你别再瞎逼逼,赶紧说重点…”
我:dalao我错了,下面说重点…
先来概括一下我们的实现思路:
把http请求框架的共性方法抽取到接口中,我们把这个接口称为“请求接口”;
创建一个用于返回请求结果的接口,我们把这个接口称为“回调接口”;
分别用Volley和OkHttp实现“请求接口”;
创建一个类来返回上述接口的对象,我们把这个类叫做“工厂”类;
在Activity/Fragment/Presenter中,使用“工厂”返回的这个接口对象调用get/post/put/delete方法,并在“回调接口”中得到请求结果。
本文完整代码https://github.com/V1sk/HttpRequestExample,可以先clone到本地再看文章,为了方便阅读,下文中的代码将省略非重点部分。
Step1:把http请求框架的共性方法抽取到接口中(也就是上述说的get/post/put/delete这些方法)
1234567891011121314151617 | /* * 此接口提供的就是http请求通用的方法,该接口可以用Volley来实现,也能用OkHttp等其它方式来实现 * 接口说明: * get方法参数包含一个url,以及返回数据的接口 * post/put/delete方法还需要提供一个请求体参数 */public interface IRequestManager { void get(String url, IRequestCallback requestCallback); void post(String url, String requestBodyJson, IRequestCallback requestCallback); void put(String url, String requestBodyJson, IRequestCallback requestCallback); void delete(String url, String requestBodyJson, IRequestCallback requestCallback);} |
12345678910111213 | /** * Created by chenjianwei on 2016/12/11. * 请求返回成功/失败,成功时,把服务器返回的结果回调出去,失败时回调异常信息 * onSuccess中的参数类型,当然也可以为JSONObject,这里只是举个栗子,可按照实际需求变通 */public interface IRequestCallback { void onSuccess(String response); void onFailure(Throwable throwable);} |
首先我们搞清楚http请求,有哪些方法,需要有哪些参数——IRequestManager;
数据返回会有什么情况?——IRequestCallback;
Step2:用Volley来实现IRequestManager这个接口.
12345678910111213141516171819202122232425262728293031323334353637383940 | public class VolleyRequestManager implements IRequestManager { ... @Override public void get(String url, final IRequestCallback requestCallback) { StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String s) { requestCallback.onSuccess(s); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { requestCallback.onFailure(volleyError); } }); HttpRequestExampleApp.mQueue.add(request); } @Override public void post(String url, String requestBodyJson, final IRequestCallback requestCallback) { requestWithBody(url, requestBodyJson, requestCallback, Request.Method.POST); } @Override public void put(String url, String requestBodyJson, final IRequestCallback requestCallback) { requestWithBody(url, requestBodyJson, requestCallback, Request.Method.PUT); } @Override public void delete(String url, String requestBodyJson, final IRequestCallback requestCallback) { requestWithBody(url, requestBodyJson, requestCallback, Request.Method.DELETE); } ...} |
Step3:创建一个类来返回IRequestManager请求接口的对象
1234567891011121314 | /* * 该类的作用是用于返回一个IRequestManager对象,这个IRequestManager的实现类 * 可以是使用Volley实现的http请求对象,也可以是OkHttp实现的http请求对象 * Activity/Fragment/Presenter中,只要调用getRequestManager()方法就能得到 * http请求的操作接口,而不用关心具体是使用什么实现的。 */public class RequestFactory { public static IRequestManager getRequestManager(){ return VolleyRequestManager.getInstance(); //return OkHttpRequestManager.getInstance(); } } |
使用RequestFactory的方式在Activity/Fragment/Presenter中创建对象,代码只依赖了IRequestManager这个接口,这就是使用接口进行解耦的关键点,无论在什么地方使用了这个接口,当要更换实现的时候,只需要修改RequestFactory中return的实现类就可以了。
Step4:调用上述方法进行测试
1234567891011121314151617181920212223242526272829 | public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //请求测试url String url = "https://api.douban.com/v2/movie/top250"; //这里发起请求依赖的是IRequestManager接口,而没有具体实现类代码出现在这里 IRequestManager requestManager = RequestFactory.getRequestManager(); //调用接口的get方法 requestManager.get(url, new IRequestCallback() { @Override public void onSuccess(String response) { Log.d(TAG, "onSuccess: " + response); //// TODO: 2016/12/11 your code } @Override public void onFailure(Throwable throwable) { throwable.printStackTrace(); //// TODO: 2016/12/11 your code } }); }} |
IRequestManager requestManager = RequestFactory.getRequestManager();
Step5:不更改MainActivity中任何代码,把Http请求的逻辑替换成OkHttp来实现
1)先用OkHttp来实现IRequestManager这个接口.123456789101112131415161718192021222324252627282930313233343536 | public class OkHttpRequestManager implements IRequestManager { ... @Override public void get(String url, IRequestCallback requestCallback) { Request request = new Request.Builder() .url(url) .get() .build(); addCallBack(requestCallback, request); } @Override public void post(String url, String requestBodyJson, IRequestCallback requestCallback) { RequestBody body = RequestBody.create(TYPE_JSON, requestBodyJson); Request request = new Request.Builder() .url(url) .post(body) .build(); addCallBack(requestCallback, request); } @Override public void put(String url, String requestBodyJson, IRequestCallback requestCallback) { ... } @Override public void delete(String url, String requestBodyJson, IRequestCallback requestCallback) { ... } ... } |
现在我们用OkHttp的请求方式也实现了一套get/post/put/delete的请求方法,此时只要修改Step3中,返回的对象为OkHttpRequestManager对象,就已经完成了我们整个http请求框架的更换,此时,你可以完全移除Volley的引用以及代码,而不会对程序有任何影响。
总结:
对于有多种可替代解决方案的业务逻辑,我的解耦思路是这样的:抽取它们的共性方法到接口中;
使用自己选择的实现方案去实现;
使用“工厂”类把具体实现转换成抽象接口,并返回抽象接口对象;
Activity/Fragment/Presenter中,使用“工厂”中返回的接口进行操作,而不要依赖于其实现类。
要更换方案的时候,只需要修改“工厂”中返回的实现类。
后记
这篇文章只是提供一种解耦思想,而不是“如何封装http请求框架”的教程,也不是讨论“哪个http请求框架好用”的文章,当然,你完全可以用这种方法进行http请求的封装。然后,这篇文章是博主的第一篇文章,可能写得不是很好,欢迎大家提出宝贵意见,一直都想写blog,可惜除了工作,还要学习,没有太充裕的时间,现在好了,公司忽然告诉我们说破产了,实在是惊魂未定,听说写作可以让人平静,于是我开始尝试写blog这个一直没有付诸行动的小心愿,写写文章压压惊。
相关文章推荐
- 对于有多种可替代解决方案的业务逻辑,提供一种快速替换方法
- 一种基于内存的快速查询的解决方案。
- 为解决ASP.NET MVC(CTP)中URL“页面请求”和“单纯逻辑处理请求”混淆问题,提供一条思路
- Spark,一种快速数据分析替代方案
- 页面级的业务对象与展现映射封装(一种开发思路与技术实现)
- Drools 为你的业务逻辑提供框架(翻译)
- 由一道逻辑推理题衍生的对于实际问题求解的一般思路
- php数据库模式设计、数据库访问和使用数据库的业务逻辑解决方案
- TWaver 为电信运营支撑系统(OSS)的开发提供“一站式”的组件产品和解决方案,是快速设计、开发和部署OSS的利器
- OpenJWeb快速开发平台自动创建基于事务的业务逻辑接口和实现类
- UI与业务逻辑分离的另一种思路
- 关于更换液晶屏(LCD)后“输入不支援”的一种解决方案
- 由一道逻辑推理题衍生的对于实际问题求解的一般思路(续)
- OBA为企业的跨职能业务流程提供生成创新解决方案的支持
- Drools 为你的业务逻辑提供框架(转载)
- 如何快速签署基于产品实施的项目业务解决方案
- 创建一种服务 为多种客户端提供ws的访问方式
- 有没有一种业务逻辑让你着迷
- 逻辑题望大家提供点思路