使用策略模式優雅引用第三方框架

爲何要使用策略模式引用?

在Android開發過程當中,咱們通常都會使用到第三方框架,隨着框架層出不窮,隨着項目的發展擴大,不排除會出現替換框架的狀況,例如:日誌框架,圖片框架,網絡框架等等;最初我在開發過程當中會直接引用第三方框架,直到後來須要替換框架的時候,才發現這個過程的工做量是巨大而且沒意義的,須要修改使用到框架的地方有幾十處(若是項目大,遠遠不止這個數目),那時候我就醒悟,必定要培養架構思想,不能應付式的實現了功能就認爲萬事大吉。後來在學習過程當中發現,使用策略模式能夠很友好的解決框架更換的問題,而且能夠經過一句代碼就輕鬆切換整個項目的框架。git


    不使用策略模式封裝也能夠呀!

    或許會有讀者認爲不必使用策略模式這麼麻煩,只須要將框架進行二次封裝,待須要修改的時候也能夠不影響其餘代碼。對於這種思路,我用圖片框架Universal-Image-Loader做爲例子簡單描述一下,貼上簡短的代碼便於清晰。github

    /**
    * 簡單封裝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的地方。bash

    /**
    * 使用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等等。app

    /**
        * 策略接口
        **/
       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);
        }
    
    }複製代碼


    完成實現類後,最後寫一個調用的工具類就完成了封裝。ide

    /**
    * 調用圖片框架的工具類
    **/
    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,有興趣的讀者不妨下載閱讀,更深的瞭解(源碼有註釋)。

    看完圖片框架的封裝,你們不妨嘗試封裝日誌框架進行理解並鞏固,將這種思想融會貫通。

    若是這篇文章寫的有錯漏,懇請留言提示糾正;若是有什麼地方描述的不夠清晰,留下評論,我看到會給予回覆,一塊兒交流;若是這篇文章對你有所幫助,不妨點擊「喜歡」給予支持,往後我會努力抽空分享自我以爲不錯的知識點給你們。

    相關文章
    相關標籤/搜索