使用策略模式封裝第三方框架

why? 封裝

Android 發(fā)展到現在這個時期, 出現了各種成熟好用的第三方框架, 使用這些第三方框架來完成我們自己的App的功能是很方便的. 但是最好不要直接的去使用這些第三方框架, 因為可能隨著項目的功能迭代, 一開始確定的框架后來并不能滿足我們的需求, 這個時候如果沒有做封裝, 要修改它們就是一個繁雜的事情了. 因此需要對框架進行封裝. 還有一個好處就是方便修改統(tǒng)一的配置.

how? 封裝

通常我們封裝一個框架都是會寫一些工具類,然后通過工具類來完成功能的封裝, 這樣寫,當然是OK的, 但是真到了需要換框架的時候, 做修改可能需要把以前寫的代碼都刪除掉, 然后寫上新的代碼, 這樣做并不好,有沒有一個辦法, 就是說新的代碼在加上的時候老的代碼不需要刪除掉, 只是做不同的配置呢. 這樣一來如果的新的東西有問題, 還是可以及時配置成之前的. 這樣就降低了開發(fā)的風險,增加了代碼的靈活度. 這里就需要使用策略模式來完成了.

舉個栗子

今天就以圖片框架舉栗子, 看看怎么使用策略模式進行封裝.
對于圖片加載框架,大家用到的可能是Glide,Picasso或者Fresco,這基本上是主流的圖片加載框架.
先看Glide加載圖片的代碼:

Glide.with(getContext())
                .load(url)
                .skipMemoryCache(true)
                .placeholder(drawable)
                .centerCrop()
                .animate(animator)
                .into(img);

定義策略

不管是什么圖片加載框架都是需要做一些配置的. 把這些配置封裝起來. 配置中相同的東西可以抽取出去.
如下

public class ImageLoaderOptions {

    //你可以把三個圖片加載框架所有的共同或相似設置項搬過來,現在僅僅用以下幾種作為范例演示。
    private int placeHolder = -1; //當沒有成功加載的時候顯示的圖片
    private ImageReSize size = null; //重新設定容器寬高
    private int errorDrawable = -1;  //加載錯誤的時候顯示的drawable
    private boolean isCrossFade = false; //是否漸變平滑的顯示圖片
    private boolean isSkipMemoryCache = false; //是否跳過內存緩存
    private ViewPropertyAnimation.Animator animator = null; // 圖片加載動畫

    private ImageLoaderOptions(ImageReSize resize, int placeHolder, int errorDrawable, boolean isCrossFade, boolean isSkipMemoryCache, ViewPropertyAnimation.Animator animator) {
        this.placeHolder = placeHolder;
        this.size = resize;
        this.errorDrawable = errorDrawable;
        this.isCrossFade = isCrossFade;
        this.isSkipMemoryCache = isSkipMemoryCache;
        this.animator = animator;
    }

    public class ImageReSize {
        int reWidth = 0;
        int reHeight = 0;

        public ImageReSize(int reWidth, int reHeight) {
            if (reHeight <= 0) {
                reHeight = 0;
            }
            if (reWidth <= 0) {
                reWidth = 0;
            }
            this.reHeight = reHeight;
            this.reWidth = reWidth;

        }

    }


    public int getPlaceHolder() {
        return placeHolder;
    }

    public void setPlaceHolder(int placeHolder) {
        this.placeHolder = placeHolder;
    }

    public ImageReSize getSize() {
        return size;
    }

    public void setSize(ImageReSize size) {
        this.size = size;
    }

    public int getErrorDrawable() {
        return errorDrawable;
    }

    public void setErrorDrawable(int errorDrawable) {
        this.errorDrawable = errorDrawable;
    }

    public boolean isCrossFade() {
        return isCrossFade;
    }

    public void setCrossFade(boolean crossFade) {
        isCrossFade = crossFade;
    }

    public boolean isSkipMemoryCache() {
        return isSkipMemoryCache;
    }

    public void setSkipMemoryCache(boolean skipMemoryCache) {
        isSkipMemoryCache = skipMemoryCache;
    }

    public ViewPropertyAnimation.Animator getAnimator() {
        return animator;
    }


    public static final  class Builder {
        private int placeHolder=-1;
        private ImageReSize size=null;
        private int errorDrawable=-1;
        private boolean isCrossFade =false;
        private  boolean isSkipMemoryCache = false;
        private   ViewPropertyAnimation.Animator animator = null;
        public Builder (){

        }
        public Builder placeHolder(int drawable){
            this.placeHolder=drawable;
            return  this;
        }

        public Builder reSize(ImageReSize size){
            this.size=size;
            return  this;
        }

        public Builder anmiator(ViewPropertyAnimation.Animator animator){
            this.animator=animator;
            return  this;
        }
        public Builder errorDrawable(int errorDrawable){
            this.errorDrawable=errorDrawable;
            return  this;
        }
        public Builder isCrossFade(boolean isCrossFade){
            this.isCrossFade=isCrossFade;
            return  this;
        }
        public Builder isSkipMemoryCache(boolean isSkipMemoryCache){
            this.isSkipMemoryCache=isSkipMemoryCache;
            return  this;
        }

        public  ImageLoaderOptions build(){

            return new ImageLoaderOptions(this.size,this.placeHolder,this.errorDrawable,this.isCrossFade,this.isSkipMemoryCache,this.animator);
        }
    }
}

定義策略的接口

public interface ImageLoaderStrategy {

    void showImage(View v, String url,ImageLoaderOptions options);

    void showImage(View v, int drawable,ImageLoaderOptions options);
}

策略的實現類 在這里用的是glide來加載圖片的

public class GlideImageLoaderStrategy implements ImageLoaderStrategy {

    @Override
    public void showImage(View v, String url, ImageLoaderOptions options) {
        if (v instanceof ImageView) {
            //將類型轉換為ImageView
            ImageView imageView= (ImageView) v;
            //裝配基本的參數
            DrawableTypeRequest dtr = Glide.with(imageView.getContext()).load(url);
            //裝配附加參數
            loadOptions(dtr, options).into(imageView);
        }
    }

    @Override
    public void showImage(View v, int drawable, ImageLoaderOptions options) {
        if (v instanceof ImageView) {
            ImageView imageView= (ImageView) v;
            DrawableTypeRequest dtr = Glide.with(imageView.getContext()).load(drawable);
            loadOptions(dtr, options).into(imageView);
        }
    }

    //這個方法用來裝載由外部設置的參數
    private DrawableTypeRequest loadOptions(DrawableTypeRequest dtr,ImageLoaderOptions options){
        if (options==null) {
            return dtr;
        }
        if (options.getPlaceHolder()!=-1) {
            dtr.placeholder(options.getPlaceHolder());
        }
        if (options.getErrorDrawable()!=-1){
            dtr.error(options.getErrorDrawable());
        }
        if (options.isCrossFade()) {
            dtr.crossFade();
        }
        if (options.isSkipMemoryCache()){
            dtr.skipMemoryCache(options.isSkipMemoryCache());
        }
        if (options.getAnimator()!=null) {
            dtr.animate(options.getAnimator());
        }
        if (options.getSize()!=null) {
            dtr.override(options.getSize().reWidth,options.getSize().reHeight);
        }
        return dtr;
    }

}

加載圖片定義接口

public interface ImageLoader {

    void showImage(@NonNull View mView, @NonNull String mUrl);

    void showImage(@NonNull View mView, @NonNull int mDraeables);
}

管理類去實現這個接口.

public class ImageLoaderManager implements ImageLoader{

    private static final ImageLoaderManager INSTANCE = new ImageLoaderManager();
    private ImageLoaderStrategy imageLoader;
    private ImageLoaderOptions options;

    private ImageLoaderManager() {
        //默認使用Glide  --> 在這里修改默認的圖片加載框架
        imageLoader = new GlideImageLoaderStrategy();
        options =  new ImageLoaderOptions.Builder().build();
    }

    public static ImageLoaderManager getInstance() {
        return INSTANCE;
    }

    //可實時替換圖片加載框架
    public void setImageLoader(ImageLoaderStrategy loader) {
        if (loader != null) {
            imageLoader = loader;
        }
    }

    @Override
    public void showImage(@NonNull View mView, @NonNull String mUrl) {
        imageLoader.showImage(mView, mUrl, options);
    }

    @Override
    public void showImage(@NonNull View mView, @NonNull int mDraeables) {
        imageLoader.showImage(mView, mDraeables, options);
    }

}

使用

  ImageLoaderManager.getInstance().showImage(iv,URL1);

總結

使用策略模式封裝的思路.

  • 先定義出Manager的接口來約束Manger類,可以做什么事情, 這里面參數應該是盡可能的少.
  • 接口有了, manager類的實現可以寫了 manager類中需要定義 策略 和 參數. 通過這些變量完成接口中需要實現的功能. 變量應該在構造函數中完成初始化.
  • 定義策略類的接口
  • 接口的實現類, 圖片有三種網絡框架,這里就可以定義三個策略的實現類. 每個實現類中去完成不同的圖片加載方式.
Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,523評論 25 708
  • 發(fā)現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,252評論 4 61
  • 實在不怎么滿意第一次畫的效果,這次我換了比較光滑的A4紙,加上了背景,還是好多了吧(?ò ? ó?) 額,我怎么看...
    畫畫的半山閱讀 268評論 0 2
  • 了卻浮塵莫問回,情在清瞳媚在眉。 冰雪對香霏。 噙霜闋里,遙寄一枝梅。
    陶然忘機閱讀 276評論 2 4
  • 書上的靈魂是一個少年,是一個酷愛讀書,渴望知識的男孩——我。在那孤獨的歲月里,書就像我的朋友陪伴著我,像我的老師教...
    凌尊閱讀 232評論 1 4