策略模式實現 retrofit 的get和post請求的公共參數(一)

策略模式的作用,作用是替換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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章