策略模式
意圖:定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。
主要解決:在有多種算法相似的情況下,使用if...else
所帶來的複雜和難以維護。
何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行爲。
如何解決:將這些算法封裝成一個一個的類,任意地替換。
關鍵代碼:實現同一個接口。
應用實例:
1、諸葛亮的錦囊妙計,每一個錦囊就是一個策略。
2、旅行的出遊方式,選擇騎自行車、坐汽車,每一種旅行方式都是一個策略。
3、JAVA AWT
中的LayoutManager
。
優點: 1、算法可以自由切換。 2、避免使用多重條件判斷。 3、擴展性良好。
缺點: 1、策略類會增多。 2、所有策略類都需要對外暴露。
使用場景:
1、如果在一個系統裏面有許多類,它們之間的區別僅在於它們的行爲,那麼使用策略模式可以動態地讓一個對象在許多行爲中選擇一種行爲。
2、一個系統需要動態地在幾種算法中選擇一種。
3、如果一個對象有很多的行爲,如果不用恰當的模式,這些行爲就只好使用多重的條件選擇語句來實現。
注意事項:如果一個系統的策略多於四個,就需要考慮使用混合模式,解決策略類膨脹的問題。
ps:以下代碼來源與網絡,忘記出處了,侵立刪。
圖片加載庫
- 定義接口
public interface IimageListener {
void display(Context context, ImageView imageView, String url, int progressId, int errorId,
Object tag);
void display(Context context, ImageView imageView, String url, int progressId, int errorId);
void display(Context context, ImageView imageView, String url, int progressId);
void display(Context context, ImageView imageView, String url);
void display(Context context, ImageView imageView, Uri uri);
}
- 實現接口
public class GlideRequest implements IimageListener {
@Override
public void display(Context context, ImageView imageView, String url, int progressId, int
errorId, Object tag) {
DrawableTypeRequest<String> load = Glide.with(context).load(url);
if (progressId != -1) {
load.placeholder(progressId).centerCrop();
} else {
load.placeholder(new ColorDrawable(Color.GRAY));
}
if (errorId != -1) {
load.error(errorId);
}else{
load.error(R.drawable.ic_error);
}
load.into(imageView);
}
@Override
public void display(Context context, ImageView imageView, String url, int progressId, int
errorId) {
display(context, imageView, url, progressId, errorId, null);
}
@Override
public void display(Context context, ImageView imageView, String url, int progressId) {
display(context, imageView, url, progressId, -1, null);
}
@Override
public void display(Context context, ImageView imageView, String url) {
display(context, imageView, url, -1, -1, null);
}
@Override
public void display(Context context, ImageView imageView, Uri uri) {
DrawableTypeRequest<Uri> load = Glide.with(context).load(uri);
load.into(imageView);
}
}
public class PicassoRequest implements IimageListener {
@Override
public void display(Context context, ImageView imageView, String url, int progressId, int
errorId, Object tag) {
Picasso.with(context).load(url).placeholder(progressId).error(errorId).tag(tag).into(imageView);
}
@Override
public void display(Context context, ImageView imageView, String url, int progressId, int
errorId) {
Picasso.with(context).load(url).placeholder(progressId).error(errorId).into(imageView);
}
@Override
public void display(Context context, ImageView imageView, String url, int progressId) {
Picasso.with(context).load(url).placeholder(progressId).into(imageView);
}
@Override
public void display(Context context, ImageView imageView, String url) {
Picasso.with(context).load(url).into(imageView);
}
@Override
public void display(Context context, ImageView imageView, Uri uri) {
Picasso.with(context).load(uri).into(imageView);
}
}
- 實現類
public class ImageRequestManager {
public static final String type_Glide="Glide";
public static final String type_Picasso="Picasso";
public static final String type_default =type_Glide;
private ImageRequestManager(){
}
public static IimageListener getRequest(){
return getRequest(type_default);
}
public static IimageListener getRequest(String type){
switch (type){
case type_Glide:
return new GlideRequest();
case type_Picasso:
return new PicassoRequest();
default:
return new GlideRequest();
}
}
}
- 使用
ImageRequestManager.getRequest(ImageRequestManager.type_default).display(mContext, imageView, imageUrl);
網絡庫封裝
- 定義配置項
public class NetworkOption {
/**
* 網絡請求的 TAG
*/
public String mBaseUrl;
public String mTag;
public Map<String,String> mHeaders;
public NetworkOption(String tag) {
this.mTag = tag;
}
public static final class Builder{
public String tag;
public Map<String,String> mHeaders;
public String mBaseUrl;
public Builder setTag(String tag){
this.tag=tag;
return this;
}
public Builder setHeaders(Map<String,String> headers){
mHeaders=headers;
return this;
}
public Builder setBaseUrl(String baseUrl) {
mBaseUrl = baseUrl;
return this;
}
public NetworkOption build(){
NetworkOption networkOption = new NetworkOption(tag);
networkOption.mHeaders=mHeaders;
networkOption.mBaseUrl=mBaseUrl;
return networkOption;
}
}
}
- 定義接口
public interface NetRequest {
void init(Context context);
void doGet(String url, final Map<String, String> paramsMap, final IResponseListener iResponseListener);
void doGet(String url, final Map<String, String> paramsMap, NetworkOption networkOption, final IResponseListener iResponseListener);
void doPost(String url, final Map<String, String> paramsMap, final IResponseListener iResponseListener);
void doPost(String url, final Map<String, String> paramsMap, NetworkOption networkOption,
final IResponseListener iResponseListener);
void cancel(Object tag);
}
- 定義具體的網絡請求
public class OKHttpRequest implements NetRequest {
static int cacheSize = 10 * 1024 * 1024; // 10 MiB
private static OkHttpClient client ;
private Context mContext;
public static Handler mHandler=new Handler();
public static Handler getHandler(){
if(mHandler==null){
mHandler=new Handler();
}
return mHandler;
}
@Override
public void init(Context context) {
mContext = context.getApplicationContext();
client=getCilent();
}
private volatile static OKHttpRequest instance = null;
private OKHttpRequest(){
}
public static OKHttpRequest getInstance() {
if (instance == null) {
synchronized (OKHttpRequest.class) {
if (instance == null) {
instance = new OKHttpRequest();
}
}
}
return instance;
}
private OkHttpClient getCilent() {
if(client==null){
OkHttpClient.Builder mBuilder= new OkHttpClient.Builder().
connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.cache(new Cache(mContext.getExternalFilesDir("okhttp"),cacheSize));
client=mBuilder.build();
}
return client;
}
@Override
public void doGet(String url, Map<String, String> paramsMap, final IResponseListener iResponseListener) {
doGet(url,paramsMap,null,iResponseListener);
}
@Override
public void doGet(String url, Map<String, String> paramsMap, NetworkOption networkOption,
final IResponseListener iResponseListener) {
url= NetUtils.checkUrl(url);
url=NetUtils.appendUrl(url,paramsMap);
final NetworkOption option=NetUtils.checkNetworkOption(networkOption,url);
Request.Builder builder = new Request.Builder().url(url).tag(option.mTag);
builder=configHeaders(builder,option);
Request build = builder.build();
getCilent().newCall(build).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handleError(e, iResponseListener);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
handleResult(response, iResponseListener);
}
});
}
private Request.Builder configHeaders(Request.Builder builder, NetworkOption option) {
Map<String, String> headers = option.mHeaders;
if(headers==null || headers.size()==0){
return builder;
}
Set<Map.Entry<String, String>> entries = headers.entrySet();
for(Map.Entry<String, String> entry: entries){
String key = entry.getKey();
String value = entry.getValue();
// 添加請求頭
builder.addHeader(key,value);
}
return builder;
}
@Override
public void doPost(String url, Map<String, String> paramsMap, final IResponseListener iResponseListener) {
doPost(url,paramsMap,null,iResponseListener);
}
private FormBody.Builder configPushParam(FormBody.Builder builder, Map<String, String> paramsMap) {
if(paramsMap!=null){
Set<Map.Entry<String, String>> entries = paramsMap.entrySet();
for(Map.Entry<String,String> entry:entries ){
String key = entry.getKey();
String value = entry.getValue();
builder.add(key,value);
}
}
return builder;
}
@Override
public void doPost(String url, Map<String, String> paramsMap, NetworkOption networkOption,
final IResponseListener iResponseListener) {
url= NetUtils.checkUrl(url);
final NetworkOption option=NetUtils.checkNetworkOption(networkOption,url);
// 以表單的形式提交
FormBody.Builder builder = new FormBody.Builder();
builder=configPushParam(builder,paramsMap);
FormBody formBody = builder.build();
Request.Builder requestBuilder = new Request.Builder().url(url).post(formBody).tag(option.mTag);
requestBuilder=configHeaders(requestBuilder,option);
Request request = requestBuilder.build();
getCilent().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handleError(e,iResponseListener);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
handleResult(response,iResponseListener);
}
});
}
@Override
public void cancel(Object tag) {
if(client!=null){
if(client != null) {
// 在等待隊列中查找是否有相應的請求
for(Call call : client.dispatcher().queuedCalls()) {
if(call.request().tag().equals(tag))
call.cancel();
}
// 在正在請求的請求隊列中查找是否有相應的請求
for(Call call : client.dispatcher().runningCalls()) {
if(call.request().tag().equals(tag))
call.cancel();
}
}
}
}
}
- 管理類
public class NetManger {
private static NetRequest instance;
private static Context mContext;
public static NetRequest getRequest(){
return instance;
}
static HashMap<String,NetRequest> mMap=new HashMap<>();
public static void init(Context context){
instance = OKHttpRequest.getInstance();
mContext = context.getApplicationContext();
instance.init(NetManger.mContext);
}
// 採用反射的形式實現,這樣有一個好處是,以後增加新的實現類的話,我們只需要傳遞相應 的 Class,
//而不需要更改 NetManger 的代碼
public static <T extends NetRequest> NetRequest getRequest(Class<T> clz){
String simpleName = clz.getSimpleName();
NetRequest request = mMap.get(simpleName);
if(request ==null){
try {
Constructor<T> constructor = clz.getDeclaredConstructor();
constructor.setAccessible(true);
request = constructor.newInstance();
request.init(mContext);
mMap.put(simpleName,request);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
instance=request;
return request;
}
}
- 使用
在 application 中 初始化
NetManger.init(application);
發起具體請求
NetManger.getRequest(OKHttpRequest.classs).doGet(url, mMap, new IResponseListener() {
@Override
public void onResponse(String response) {
LogUtil.i(TAG,"onResponse: response ="+response);
}
@Override
public void onFail(HttpException httpException) {
Log.i(TAG, "onFail: httpException=" +httpException.toString());
}
});