美文网首页设计模式
设计模式-策略模式

设计模式-策略模式

作者: h2coder | 来源:发表于2020-10-15 00:29 被阅读0次

什么是策略模式?什么时候用?

  • 提到策略模式,一般常见于算法,例如排序算法,多种策略提供排序。
  • Android中的动画的差值器,每种差值器让动画的执行变化不同,实现加、减速度等效果。

怎么实现策略模式?

  • 先定义一个外部调用的接口,每种策略作为实现。
  • 建立外部管理类,提供设置和获取策略实现的方法,调用时使用策略接口提供的Api调用即可。

策略模式实现ImageLoader

  • 平时Android开发中,总会使用一些图片加载框架,例如Glide、Fresco或者是老牌的Android-Universal-Image-Loader,而我们一般不会直接使用,而是会封装一层,方便以后切换别的框架时,不需要改动外部Api。
  1. 策略接口
public interface ImageLoaderStrategy {
    /**
     * 初始化,在application的onCreate中初始化,该方法存在意义是为了有些框架需要在Application中初始化
     */
    void init(Context context);

     /** 
     * 加载图片
     * @param option 加载可选项
     * @param targetView 目标ImageView
     */
    void load(Context context, LoadOption option, ImageView targetView);

    /**
     * 清除内存缓存
     */
    void clearMemoryCache(Context context);
    
    /**
     * 清除磁盘缓存
     */
    void clearDiskCache();

    /**
     * 暂停请求,一般在ListView或RecyclerView滚动时调用,停止加载快速滚动的图片数据
     */
    void pause(Context context);

    /**
     * 恢复请求,在ListView或RecyclerView滚动停止时调用
     */
    void resume(Context context);
}
  1. 加载参数,不是策略模式的必须,只是该例子需要
public class ImageOption {
    private String url;

    public ImageOption(Builder builder) {
        this.url = builder.url;
    }

    public static class Builder {
        private String url;
        //...这里可以加其他参数,现在只提供一个url参数演示
        
        public Builder setUrl(String url){
            this.url = url;
        }
        
        public ImageOption build() {
            return new ImageOption(this);
        }
    }
}
  1. 统一的外部门面类
public class ImageLoader {
    private ILoaderStrategy mLoader;
    private Context mContext;

    public ImageLoader with(Context context) {
        mContext = context;
        return this;
    }

    public Context getContext() {
        return mContext;
    }

    public void setLoader(ILoaderStrategy loader) {
        mLoader = loader;
    }

    public ILoaderStrategy getLoader() {
        return mLoader;
    }
}
  1. 具体实现
  • Glide实现
public class GlideLoader implements ILoaderStrategy {
    private Context mApplicationContext;

    @Override
    public void init(Context context) {
        mApplicationContext = context.getApplicationContext();
        //做一些初始化操作...
    }

    @Override
    public void load(@NotNull Context context, @NotNull LoadOption option, @NotNull ImageView targetView) {
        //1、根据option中的资源类型决定加载的资源类型
        //2、变换、裁剪操作
        //3、加载
        Glide.with(context).load(xxx).into(targetView);
    }

    @Override
    public void clearMemoryCache(int level) {
        Context context = ImageLoader.getContext();
        // clear Glide cache
        if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            Glide.get(context).clearMemory();
        }
        // trim memory
        Glide.get(context).trimMemory(level);
    }

    @Override
    public void clearDiskCache() {
        Glide.get(ImageLoader.getContext()).clearDiskCache();
    }

    @Override
    public void pause(Context context) {
        Glide.with(context).pauseRequests();
    }

    @Override
    public void resume(Context context) {
        Glide.with(context).resumeRequests();
    }
}
  • Fresco实现,同样建立一个ILoaderStrategy接口的实现类
public class FrescoLoader implements ILoaderStrategy {
    private Context mApplicationContext;

    @Override
    public void init(Context context) {
        mApplicationContext = context.getApplicationContext();
        //做一些初始化操作...
    }

    @Override
    public void load(@NotNull Context context, @NotNull LoadOption option, @NotNull ImageView targetView) {
        //1、根据option中的资源类型决定加载的资源类型
        //2、变换、裁剪操作
        //3、加载
    }

    @Override
    public void clearMemoryCache(int level) {
        Fresco.getImagePipeline().clearMemoryCaches();
    }

    @Override
    public void clearDiskCache() {
        Fresco.getImagePipeline().clearDiskCaches();
    }

    @Override
    public void pause(Context context) {
        Fresco.getImagePipeline().pause();
    }

    @Override
    public void resume(Context context) {
        Fresco.getImagePipeline().resume();
    }
}
  1. 初始化,在Application中初始化,设置策略对象
ImageLoader.with(this).setLoader(new GlideLoader());
  1. 调用
ImageLoader.getLoader().load(context, new LoadOption.Builder().setUrl("www.xxxx.jpg").build(), holder.vImage);

总结

  • 切换不同的图片加载器实现,在初始化时设置不同的Loader实例即可。
  • 拓展方便。如果需要使用另外的加载框架,新建一个实现类做对应的操作即可,对外API是不变的,外部使用都不需要改动。
  • 高内聚,低耦合。对外都是依赖封装的ImageLoader,外部不需要关注内部实现是谁,怎么处理。

相关文章

网友评论

    本文标题:设计模式-策略模式

    本文链接:https://www.haomeiwen.com/subject/axompktx.html