策略模式實現 retrofit 的get和post請求的公共引數(一)
阿新 • • 發佈:2018-12-27
策略模式的作用,作用是替換if,elst if ,switch case,可是為什麼我就替換不了呢?
比如:
圖書價格,初級會員9折,高階會員打8折
通常實現:
private double getPrice(int grade, double price) {
switch (grade) {
case 1:
//初級會員
price = price * 0.9;
break;
case 2:
//高階會員
price = price * 0.8;
break;
}
return price;
}
//或者
private double getPrice(int grade, double price) {
if (grade == 1) {
price = price * 0.9;
} else if (grade == 2) {
price = price * 0.8;
}
return price;
}
//或者
private double getPrice(int grade, double price) {
if (grade == 1) {
return price * 0.9;
}
if (grade == 2) {
return price * 0.8;
}
return price;
}
當然第三種寫法沒必要
策略模式實現:
public interface IPrice {
public double calcPrice (double price);
}
//初級
public class Primary implements IPrice{
@Override
public double calcPrice(double price) {
return price * 0.9;
}
}
//高階
public class Senior implements IPrice{
@Override
public double calcPrice(double price) {
return price * 0.8;
}
}
//上下文
public class PriceContext {
private IPrice iPrice;
public PriceContext(IPrice iPrice){
this.iPrice = iPrice;
}
public double count(double price){
return iPrice.calcPrice(price);
}
}
//客戶端(需求:根據會員等級判斷,得到相應的一個價格)
方案一:
private double getPrice(int grade, double price) {
price = new PriceContext(new Primary()).count(price);
price = new PriceContext(new Senior()).count(price);
return price;
}
方案一相當於
if(1){初級會員}
if(2){高階會員}
也就是說其中一個方案得到價格後,仍然會去判斷第二個,當然不是我想要的
方案二:
private double getPrice(int grade, double price) {
switch (grade) {
case 1:
//初級會員
price = new PriceContext(new Primary()).count(price);
break;
case 2:
//高階會員
price = new PriceContext(new Senior()).count(price);
break;
}
return price;
}
貌似符合要求了,但是策略模式就是為了解決if elseif switch case 的啊,
怎麼用了策略模式我還是寫了switch case
如果此時我想增加一箇中級會員,是不是要再加一個case,說好的開閉原則呢?
我們期望的:
新增一箇中級會員,我不想修改客戶端
//好辦,還有一個上下文可以修改,我們把客戶端的程式碼放在客戶端就好了
public class PriceContext {
private IPrice iPrice;
private int grade;
public PriceContext(int grade){
this.grade = grade;
}
public double count(double price){
switch (grade) {
case 1:
//初級會員
iPrice = new Primary();
break;
case 2:
//高階會員
iPrice = new Senior();
break;
}
return iPrice.calcPrice(price);
}
}
//客戶端
private double getPrice(int grade, double price) {
price = new PriceContext(grade).count(price);
return price;
}
此時如果增加一箇中級會員,直接在Context中增加一個case即可,客戶端無需修改
下面進入正題,同樣的方法實現retrofit在get和post中的公共引數配置
retrofit中公共引數是通過攔截器進行配置的
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(factory.initQuery(context));
//公共引數
public Interceptor initQuery(final Context context) {
Interceptor addQueryParameterInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//配置公共引數
request = new ParamsContext(request, context).getInRequest();
return chain.proceed(request);
}
};
return addQueryParameterInterceptor;
}
照葫蘆畫瓢
public interface IRequestParam {
Request getRequest(Request request, Context context);
}
//get
public class GetRequestParams implements IRequestParam {
@Override
public Request getRequest(Request request, Context context) {
//新增公共引數
HttpUrl modifiedUrl = request.url().newBuilder()
.addQueryParameter(CLIENT, AppTools.getClient(context))
.addQueryParameter(VERSION, AppTools.getAppVersion(context))
.addQueryParameter(TOKEN, AppTools.getToken(context))
.build();
return request.newBuilder().url(modifiedUrl).build();
}
}
//post
public class PostRequestParams implements IRequestParam {
@Override
public Request getRequest(Request request, Context context) {
if (request.body() instanceof FormBody) {
FormBody.Builder bodyBuilder = new FormBody.Builder();
FormBody formBody = (FormBody) request.body();
for (int i = 0; i < formBody.size(); i++) {
bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
}
formBody = bodyBuilder.addEncoded(CLIENT, AppTools.getClient(context))
.addEncoded(VERSION, AppTools.getAppVersion(context))
.addEncoded(TOKEN, AppTools.getToken(context))
.build();
request = request.newBuilder().post(formBody).build();
}
return request;
}
}
//上下文
public class ParamsContext {
private IRequestParam iRequestParam;
private Context context;
private Request request;
public ParamsContext(Request request, Context context) {
this.context = context;
this.request = request;
}
public Request getInRequest() {
switch (request.method()) {
case "GET":
iRequestParam = new GetRequestParams();
break;
case "POST":
iRequestParam = new PostRequestParams();
break;
}
return iRequestParam.getRequest(request, context);
}
}