设计模式-策略模式
2020-10-15 本文已影响0人
h2coder
什么是策略模式?什么时候用?
- 提到策略模式,一般常见于算法,例如排序算法,多种策略提供排序。
- Android中的动画的差值器,每种差值器让动画的执行变化不同,实现加、减速度等效果。
怎么实现策略模式?
- 先定义一个外部调用的接口,每种策略作为实现。
- 建立外部管理类,提供设置和获取策略实现的方法,调用时使用策略接口提供的Api调用即可。
策略模式实现ImageLoader
- 平时Android开发中,总会使用一些图片加载框架,例如Glide、Fresco或者是老牌的Android-Universal-Image-Loader,而我们一般不会直接使用,而是会封装一层,方便以后切换别的框架时,不需要改动外部Api。
- 策略接口
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);
}
- 加载参数,不是策略模式的必须,只是该例子需要
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);
}
}
}
- 统一的外部门面类
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;
}
}
- 具体实现
- 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();
}
}
- 初始化,在Application中初始化,设置策略对象
ImageLoader.with(this).setLoader(new GlideLoader());
- 调用
ImageLoader.getLoader().load(context, new LoadOption.Builder().setUrl("www.xxxx.jpg").build(), holder.vImage);
总结
- 切换不同的图片加载器实现,在初始化时设置不同的Loader实例即可。
- 拓展方便。如果需要使用另外的加载框架,新建一个实现类做对应的操作即可,对外API是不变的,外部使用都不需要改动。
- 高内聚,低耦合。对外都是依赖封装的ImageLoader,外部不需要关注内部实现是谁,怎么处理。