使用策略模式優雅引用第三方框架
為什麼要使用策略模式引用?
在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 implements BaseImageLoaderStrategy { private BaseImageLoaderStrategy mImageLoaderStrategy; private ImageLoaderUtils() { //預設使用Universal-Image-Loader mImageLoaderStrategy = new UniversalLoaderStrategy();} /** * 設定圖片框架策略 * @param strategy圖片框架策略 **/ public 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,有興趣的讀者不妨下載閱讀,更深的瞭解(原始碼有註釋)。
看完圖片框架的封裝,大家不妨嘗試封裝日誌框架進行理解並鞏固,將這種思想融會貫通。
如果這篇文章寫的有錯漏,懇請留言提示糾正;如果有什麼地方描述的不夠清晰,留下評論,我看到會給予回覆,一起交流;如果這篇文章對你有所幫助,不妨點選“喜歡”給予支援,日後我會努力抽空分享自我覺得不錯的知識點給大家。