我们使用 MVP + 策略模式模拟一个简单的登录功能
MVP + retorfit + rx 请求策略简单的 UML
首先我们要使用 AsyncHttpClient、Retorfit 等,先添加配置 Gradle「项目 Module 的 build.grade中」
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.5'
compile 'com.loopj.android:android-async-http:1.4.9'
注: 以下代码纯粹是为了演示策略模式,顺手写的,好多细节可能没有考虑到,但是基本框架就是这样的,可以自行完善
- 1、分别新建 MVP 的基类接口,IPresenter,Model,IView
/**
* @Description MVP 中的 Presenter 基
* @Creator TigerChain(创建者)
*/
public interface Presenter {
}
/**
* @Description MVP 中的 Model 基类
* @Creator TigerChain(创建者)
*/
public interface Model {
}
/**
* @Description MVP 中的 View 基类
* @Creator TigerChain(创建者)
*/
public interface IView {
}
- 2、新建 MVP 的关联接口
ILoginContact.java
「当然也可以不写此类,直接写登录 MVP 的直接子类」
package designpattern.tigerchain.com.mvphttpstrategy.mvp;
import designpattern.tigerchain.com.mvphttpstrategy.mvp.domain.User;
import io.reactivex.Observable;
/**
* @Description MVP 的关联类「也可以单独创建 MVP 就是有点乱」
* @Creator TigerChain(创建者)
*/
public interface ILoginContact {
interface LoginView extends IView{
//显示进度条
void showProgress() ;
//隐藏进度条
void hideProgress() ;
//登录成功
void loadSuccess(String str) ;
//登录失败
void loadFailed(String str) ;
//取得用户名
String getUserName() ;
//取得用户密码
String getUserPass() ;
//清除输入框
void clearEditText() ;
//用户名和密码不能为空
void editnotNull() ;
}
interface LoginPresenter extends Presenter{类
/**
* 登录功能
*/
void login() ;
/**
* 清除输入框架内容
*/
void clear() ;
}
interface ILoginModel extends Model{
/***
* 登录的方法,其实这里就是一个抽象策略,至于你使用 retrofit 还是 asynchttpClient 还是 Volley 那是自己的事情
* @param uName
* @param uPass
* @return
*/
Observable login(String uName, String uPass) ;
}
}
其中 ILoginModel 就是一个抽象策略,这里是登录功能
- 3、分别实现具体的策略「使用不同的网络请求库调用登录 API」
具体策略1:使用 AsyncHttpClient 调用登录
/**
* @Description 具体策略使用 AsyncHttpClient 来调用登录 API
* @Creator TigerChain(创建者)
*/
public class AsynchHppClientImplLogimModel implements ILoginContact.ILoginModel {
@Override
public Observable login(final String uName, final String uPass) {
return Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(final ObservableEmitter e) throws Exception {
AsyncHttpClient client = new AsyncHttpClient() ;
// 这里就是一个请求 没有真正的对接服务器,只是一个演示
client.get("http://www.baidu.com", new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
if(uName.equalsIgnoreCase("TigerChain") && uPass.equals("123")){
User user = new User() ;
user.setuName(uName);
user.setUpass(uPass);
e.onNext(user);
e.onComplete();
}else{
e.onNext(null);
e.onComplete();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
e.onError(error);
}
}) ;
}
});
}
}
具体策略2:使用 Volley 调用登录 API
/**
* @Description 具体策略使用 Volley 实现登录功能
* @Creator TigerChain(创建者)
*/
public class VolleyImplLoginModel implements ILoginContact.ILoginModel {
@Override
public Observable login(final String uName, final String uPass) {
return Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(final ObservableEmitter e) throws Exception {
/***
* 这里调用和 Volley 相关的 API 实现登录即可
*/
}
});
}
}
具体策略3:使用 RetorFit 调用登录 API
/**
* @Description 具体策略 使用 RetorFit 实现登录功能性
* @Creator TigerChain(创建者)
*/
public class RetorFitImplLoginModel implements ILoginContact.ILoginModel {
@Override
public Observable login(final String uName, final String uPass) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://")
.build();
ILoginRetorfitApi loginService = retrofit.create(ILoginRetorfitApi.class) ;
return loginService.login(uName,uPass) ;
}
}
其中 User 和 ILoginRetorfitApi 类分别是:
# User.java
/**
* @Description 普通人的 Java
* @Creator TigerChain(创建者)
*/
public class User {
private String uName ;
private String Upass ;
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public String getUpass() {
return Upass;
}
public void setUpass(String upass) {
Upass = pass;
}
}
# ILoginRetorfitApi.java
/**
* @Description Retrofit API
* @Creator TigerChain(创建者)
*/
public interface ILoginRetorfitApi {
@GET("/login")
Observable login( @Field("userName") String userName,
@Field("passWord")String passWord) ;
}
- 4、策略中的上下文「这里就是我们具体的 P」 LoginPresenterImpl.java
/**
* @Description MVP 中的P ,就相当于策略中Context
* @Creator junjun(创建者)
*/
public class LoginPresenterImpl implements ILoginContact.LoginPresenter {
private ILoginContact.ILoginModel iLoginModel ;
private ILoginContact.LoginView loginView ;
public LoginPresenterImpl(ILoginContact.LoginView loginView,ILoginContact.ILoginModel iLoginModel){
this.iLoginModel = iLoginModel ;
this.loginView = loginView ;
}
@Override
public void login() {
String uName = loginView.getUserName() ;
String uPass = loginView.getUserPass() ;
if(TextUtils.isEmpty(uName) || TextUtils.isEmpty(uPass)){
loginView.editnotNull();
return ;
}
loginView.showProgress();
iLoginModel.login(uName,uPass)
// subscribeOn(Schedulers.io()) 由于 AsyncHttpClient 本身就是在子线程去请求的,所以这里为了演示把这个去掉
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(User user) {
loginView.loadSuccess("登录成功");
}
@Override
public void onError(Throwable e) {
loginView.loadFailed("用户名或密码错误,登录失败");
loginView.hideProgress();
}
@Override
public void onComplete() {
loginView.hideProgress();
}
}) ;
}
@Override
public void clear() {
loginView.clearEditText();
}
}
到此为止,我们的 MVP+RX+Retorfit 带策略的登录功能就完成了。
- 5、客户端调用「在 Activity 中调用」
下面来看客户调用,不贴代码了「放一张部分代码截图」,后面放出全部 DEMO 大家自行查看
怎么样,通过以上几个例子,相信我们对策略模式有了很好的理解了
- 6、最后运行看一下
demo 没有实现完毕,其中 Retorfit 和 Volley 没有完善,有兴趣的可以自行完善。
完整的项目代码地址:
https://github.com/buder-cp/DesignPattern/tree/master/mvp-rx-loginStrategy-master