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

why? 封裝

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

how? 封裝

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

舉個(gè)栗子

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

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

定義策略

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

public class ImageLoaderOptions {

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

    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);
}

策略的實(shí)現(xiàn)類 在這里用的是glide來加載圖片的

public class GlideImageLoaderStrategy implements ImageLoaderStrategy {

    @Override
    public void showImage(View v, String url, ImageLoaderOptions options) {
        if (v instanceof ImageView) {
            //將類型轉(zhuǎn)換為ImageView
            ImageView imageView= (ImageView) v;
            //裝配基本的參數(shù)
            DrawableTypeRequest dtr = Glide.with(imageView.getContext()).load(url);
            //裝配附加參數(shù)
            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);
        }
    }

    //這個(gè)方法用來裝載由外部設(shè)置的參數(shù)
    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);
}

管理類去實(shí)現(xiàn)這個(gè)接口.

public class ImageLoaderManager implements ImageLoader{

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

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

    public static ImageLoaderManager getInstance() {
        return INSTANCE;
    }

    //可實(shí)時(shí)替換圖片加載框架
    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);

總結(jié)

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

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

推薦閱讀更多精彩內(nèi)容

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