策略模式的作用,作用是替换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);
}
}