為什麼要使用策略模式引用?
在Android開發過程中,我們一般都會使用到第三方框架,隨著框架層出不窮,隨著專案的發展擴大,不排除會出現替換框架的情況,例如:日誌框架,圖片框架,網路框架等等;最初我在開發過程中會直接引用第三方框架,直到後來需要替換框架的時候,才發現這個過程的工作量是巨大並且沒意義的,需要修改使用到框架的地方有幾十處(如果專案大,遠遠不止這個數目),那時候我就醒悟,一定要培養架構思想,不能應付式的實現了功能就認為萬事大吉。後來在學習過程中發現,使用策略模式可以很友好的解決框架更換的問題,並且可以通過一句程式碼就輕鬆切換整個專案的框架。
不使用策略模式封裝也可以呀!
或許會有讀者認為沒必要使用策略模式這麼麻煩,只需要將框架進行二次封裝,待需要修改的時候也可以不影響其他程式碼。對於這種思路,我用圖片框架Universal-Image-Loader作為例子簡單描述一下,貼上簡短的程式碼便於清晰。
/**
* 簡單封裝Universal-Image-Loader圖片載入的工具類
**/
public class ImageLoaderUtils {
private DisplayImageOptions mImageOptions;
public ImageLoaderUtils(){
//配置UIL的初始化
ImageLoaderConfiguration configuration = ImageLoaderConfiguration.createDefault(this);
ImageLoader.getInstance().init(configuration);
mImageOptions = DisplayImageOptions.createSimple();
}
//預設載入
public static void loadImageView(Context context, String imgUrl, ImageView view) {
ImageLoader.getInstance().displayImage(imgUrl, view, mImageOptions);
}
}複製程式碼
封裝好的工具類在Activity中的示範如下:
/**
* ImageLoaderUtils的使用示範
**/
public class ExampleActivity extends AppCompatActivity{
private ImageView mIvPhoto;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mIvPhoto = findViewById(R.id.iv_cover);
ImageLoaderUtils.loadImageView(this,"url",mIvPhoto);
}
}複製程式碼
如果需要使用Glide框架替換現在的Universal-Image-Loader框架,直接修改ImageLoaderUtils工具類,這樣亦可實現不需修改所有使用到框架Universal-Image-Loader的地方。
/**
* 使用Glide替換Universal-Image-Loader的工具類
**/
public class ImageLoaderUtils {
//預設載入
public static void loadImageView(Context context, String imgUrl, ImageView view) {
Glide.with(context).load(imgUrl).into(view);
}
}複製程式碼
這樣處理固然可以替換框架,並且工作量不算大,但我認為這種處理方式有一定的弊端,剔除了舊框架程式碼,萬一日後新框架出現問題,處理工作就顯得麻煩,說白了就是這種處理方式不能並存兩種或兩種以上的框架方案,如果專案中需要切換框架的話就明顯感覺到不靈活,所以我認為引入策略模式是可取的。
開啟封裝之路
關於策略模式,這裡我就不詳細描述,日後抽空寫一篇關於“策略模式”的文章。
首先,我們定義一個策略介面,用於存放框架之間會共同使用的方法,例如:預設載入圖片,載入GIf等等。
/**
* 策略介面
**/
public interface BaseImageLoaderStrategy {
/**
* 預設方式載入圖片
* @param context 上下文
* @param view View 控制元件
* @param imgUrl 圖片URL
*/
void loadImage(Context context, ImageView view, Object imgUrl);
}
複製程式碼
第二步:接下來寫實現類,這裡我使用Universal-Image-Loader為例,簡單寫一個實現類。
/**
* Universal-Image-Loader的實現類
**/
public class UniversalLoaderStrategy implements BaseImageLoaderStrategy {
private DisplayImageOptions mImageOptions;
/**
* 初始化載入配置
*/
private void initOptions() {
ImageLoaderConfiguration configuration = ImageLoaderConfiguration.createDefault(this);
ImageLoader.getInstance().init(configuration);
mImageOptions = DisplayImageOptions.createSimple();
}
@Override
public void loadImage(Context context, ImageView view, Object imgUrl) {
ImageLoader.getInstance().displayImage(imgUrl, view, mImageOptions);
}
}複製程式碼
完成實現類後,最後寫一個呼叫的工具類就完成了封裝。
/**
* 呼叫圖片框架的工具類
**/
public class ImageLoaderUtils {
private BaseImageLoaderStrategy mImageLoaderStrategy;
private ImageLoaderUtils() {
//預設使用Universal-Image-Loader
mImageLoaderStrategy = new UniversalLoaderStrategy(); }
/**
* 設定圖片框架策略
* @param strategy 圖片框架策略
**/
public static void setImageLoaderStrategy(BaseImageLoaderStrategy strategy) {
if (strategy != null) {
mImageLoaderStrategy = strategy;
}
}
/**
* 呼叫預設載入圖片
**/
public static void loadImage( Context context, ImageView view, Object imgUrl) {
mImageLoaderStrategy.loadImage(context,view,imgUrl);
}
}複製程式碼
到此為止,就已經完成了初步的封裝,使用方式:
ImageLoaderUtils.loadImage(context, imageView, imgUrl);複製程式碼
完成了初步封裝,但如何解決框架替換的問題好像還沒提及到。兄弟不要急呀,車現在馬上要開,扶穩了。假如專案現在要使用Glide框架,那我們需要先寫一個簡單Glide的實現類。如下:
/**
* Glide的實現類
**/
public class GlideLoaderStrategy implements BaseImageLoaderStrategy {
private RequestOptions mOptions;
private ImageLoaderConfig mConfig;
/**
* 初始化載入配置
*/
private RequestOptions getOptions() {
if (mOptions == null) {
mOptions = new RequestOptions();
mOptions.error(mConfig.getErrorPicRes())
.placeholder(mConfig.getPlacePicRes())
//下載的優先順序
.priority(Priority.NORMAL)
//快取策略
.diskCacheStrategy(DiskCacheStrategy.ALL);
}
return mOptions;
}
@Override
public void loadImage(Context context, ImageView view, Object imgUrl) {
with(context)
.load(imgUrl)
.apply(getOptions())
//先載入縮圖 然後在載入全圖
.thumbnail(Contants.THUMB_SIZE)
.into(view);
}
}複製程式碼
搞定了Glide的實現類後,呼叫ImageLoaderUtils的setImageLoaderStrategy方法即可實現框架的替換,並且不影響其他程式碼。
//切換成Glide框架
ImageLoaderUtils.setImageLoaderStrategy(new GlideLoaderStrategy());複製程式碼
主要思想大概就是這樣,但實際專案中的封裝並沒有這麼簡單,為了描述這種思想,所以簡單化,在此我貼上原始碼地址:https://github.com/fansonq/ImageLoaderUtils,有興趣的讀者不妨下載閱讀,更深的瞭解(原始碼有註釋)。
看完圖片框架的封裝,大家不妨嘗試封裝日誌框架進行理解並鞏固,將這種思想融會貫通。
如果這篇文章寫的有錯漏,懇請留言提示糾正;如果有什麼地方描述的不夠清晰,留下評論,我看到會給予回覆,一起交流;如果這篇文章對你有所幫助,不妨點選“喜歡”給予支援,日後我會努力抽空分享自我覺得不錯的知識點給大家。