代理模式实现隔离层架构,自由切换三方网络请求框架

1,336 阅读3分钟

使用代理模式实现隔离层架构,目的是为了当出现一个新的网络框架的时候,可以在业务层无感的情况下自由切换网络库,实现热插拔,对业务层几乎没有影响。

1 架构图

以用户租房为例,租户相当于APP的业务层;一个用户会对比多套房子,所以会有多个房东,最终提供房源的是房东,所以房东就类似最终实现网络请求的网络库。

中介公司和中介属于隔离层,用户租房不直接和房东打交道,只和中介联系,至于中介和哪个房东沟通,用户无需关心,只要租到房子就行,所以中介就相当于一个中间代理。

2 类图

3 类图和架构图以及代码中的类相结合

4 代码

网络请求的结果需要回调给业务层,所以先要创建一个回调接口。

public interface ICallback {
    void onSuccess(String result);

    void onFailure(String error);
}

实现回调接口,把指定的的泛型JavaBean用反射的方法解析出来。然后把json转换为JavaBean回调出去。

public abstract class HttpCallback<Result> implements ICallback {

    private static final String TAG = "HttpCallback";

    @Override
    public void onSuccess(String result) {
        //获取对应的JavaBean
        Class<?> clazz = parseClassInfo(this);
        Result objResult = (Result) new Gson().fromJson(result, clazz);
        onSuccess(objResult);
    }

    public abstract void onSuccess(Result objResult);

    @Override
    public void onFailure(String error) {

    }

    private Class<?> parseClassInfo(Object object) {
        //获得导游泛型的父类
        Type type = object.getClass().getGenericSuperclass();
        Log.d(TAG, "parseClassInfo 1: "+type);
        //获取参数化类型的数组
        Type[] params = ((ParameterizedType) type).getActualTypeArguments();
        Log.d(TAG, "parseClassInfo 2: "+params.toString());
        //拿到泛型,而HttpCallback<Result>只有一个,所以取0即可得到传入的JavaBean
        return (Class<?>) params[0];
    }
}

然后创建一个接口主题类,也就是中介公司,中介公司只制定标准和规则,具体业务由自己公司的中介去处理。

public interface IHttpRequest {
    void post(String url, Map<String, Object> params, ICallback callback);

    void get(String url, ICallback callback);
}

创建代理类,也就是中介。

public class HttpHelper implements IHttpRequest {

    private static HttpHelper instance;

    public static HttpHelper obtain() {
        synchronized (HttpHelper.class) {
            if (instance == null) {
                instance = new HttpHelper();
            }
        }
        return instance;
    }

    private HttpHelper() {
    }

    private static IHttpRequest mHttpRequest;

    public static void init(IHttpRequest httpRequest) {
        mHttpRequest = httpRequest;
    }

    @Override
    public void post(String url, Map<String, Object> params, ICallback callback) {
        String finalUrl = appendParams(url, params);
        mHttpRequest.post(finalUrl, params, callback);
    }

    @Override
    public void get(String url, ICallback callback) {
        mHttpRequest.get(url, callback);
    }

    public static String appendParams(String url, Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return url;
        }

        StringBuilder urlBuilder = new StringBuilder(url);
        if (urlBuilder.indexOf("?") <= 0) {
            urlBuilder.append("?");
        } else {
            if (!urlBuilder.toString().endsWith("?")) {
                urlBuilder.append("&");
            }
        }
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            urlBuilder.append("&" + entry.getKey())
                    .append("=")
                    .append(encode(entry.getValue().toString()));
        }
        return urlBuilder.toString();
    }

    private static String encode(String str) {
        try {
            return URLEncoder.encode(str, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
}

创建一个类OkHttpRequest去具体实现网络请求,也就是房东,房东可以是多个,所以还可以有VolleyHttpRequest、XUtilsHttpRequest、xxxHttpRequest等。

public class OkHttpRequest implements IHttpRequest {

    private OkHttpClient mOkHttpClient;
    private Handler myHandler; // 此Handler是为了切换到主线程用的,处理成果

    public OkHttpRequest() {
        mOkHttpClient = new OkHttpClient();
        myHandler = new Handler();
    }

    @Override
    public void post(String url, Map<String, Object> params, ICallback callback) {
        final RequestBody requestBody = appendBody(params);
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String result = response.body().string();
                if (response.isSuccessful()) {
                    myHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(result);
                        }
                    });
                } else {
                    myHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onFailure(result);
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, IOException e) {
                myHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure("onFailure");
                    }
                });
            }
        });
    }

    @Override
    public void get(String url, ICallback callback) {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String result = response.body().string();
                if (response.isSuccessful()) {
                    myHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onSuccess(result);
                        }
                    });
                } else {
                    myHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callback.onFailure(result);
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call call, IOException e) {
                myHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onFailure("onFailure");
                    }
                });
            }
        });
    }

    // 就是为了post请求的, 参数组装
    private RequestBody appendBody(Map<String, Object> params) {
        FormBody.Builder body = new FormBody.Builder();
        if (params == null || params.isEmpty()) {
            return body.build();
        }
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            body.add(entry.getKey(), entry.getValue().toString());
        }
        return body.build();
    }
}

创建一个响应结构。

public class ResponseData {
    private String result;
    private String reason;
    private int error_code;
    private String resultcode;

    public void setResult(String result) {
        this.result = result;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public void setError_code(int error_code) {
        this.error_code = error_code;
    }

    public void setResultcode(String resultcode) {
        this.resultcode = resultcode;
    }

    public String getResult() {
        return result;
    }

    public String getReason() {
        return reason;
    }

    public int getError_code() {
        return error_code;
    }

    public String getResultcode() {
        return resultcode;
    }

    @Override
    public String toString() {
        return "ResponseData{" +
                "result='" + result + ''' +
                ", reason='" + reason + ''' +
                ", error_code=" + error_code +
                ", resultcode='" + resultcode + ''' +
                '}';
    }
}

初始化,指定网络请求库。

public class MainApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //在这里切换其他HttpRequest,即可实现自由切换网络请求库。
        HttpHelper.init(new OkHttpRequest());
//        HttpHelper.init(new VolleyRequest(this));
//        HttpHelper.init(new XUtilsRequest(this));
    }
}

业务层使用。

String url = "https://www.baidu.com";
HashMap<String, Object> params = new HashMap<>();
params.put("param1", "1");
params.put("param2", "2");

HttpHelper.obtain().post(url, params, new HttpCallback<ResponseData>() {
       @Override
       public void onSuccess(ResponseData objResult) {
              Toast.makeText(MainActivity.this, objResult.toString(), Toast.LENGTH_SHORT).show();
        }
});

关注木水小站 (zhangmushui.cn)和微信公众号【木水Code】,及时获取更多最新文章。