开闭原则
(Open Close Principle, OCP)
参考《Android 源码设计模式》
- 对扩展开放,对修改关闭。策略,可扩展
- 策略模式,模式多了不好记:用枚举插一手。算了,如果这样干,增加策略的时候,需要修改枚举类。
单一职责原则 + 开闭原则 + 策略模式,增强 ImageLoader
/** 接口如其名,定义图片缓存顶层接口 */
public interface ImageCache {
/** 从缓存中获取图片 */
Bitmap getBitmap(String key);
/** 缓存图片 */
void setBitmap(String key, Bitmap bitmap);
}
/** 内存缓存策略 */
public class MemoryCache implements ImageCache {
/** 使用 LruCache 缓存图片到内存 */
private static LruCache<String,Bitmap> mLruCache = new LruCache<String,Bitmap>((int) (Runtime.getRuntime().maxMemory() / 4)) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
@Override
public Bitmap getBitmap(String key) {
return mLruCache.get(key);
}
@Override
public void setBitmap(String key, Bitmap bitmap) {
mLruCache.put(key, bitmap);
}
}
/** 本地缓存策略 */
public class DiskCache implements ImageCache {
/** 使用 DiskLruCache 缓存图片到硬盘 */
private DiskLruCache mDiskLruCache;
public DiskCache() {
initDiskLruCache(); // 初始化 DiskLruCache
}
/** 初始化 DiskLruCache */
private void initDiskLruCache() {
Context context = AppDemoApplication.getContext();
// 参数一:可写的缓存目录
File directory = AppDemoApplication.getContext().getCacheDir();
// 参数二:
int appVersion = 1;
try {
appVersion = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
// 参数三:最大可缓存文件个数
int valueCount = 100;
// 参数四:最大缓存容量 Bytes
long maxSize= 30 * 1024 * 1024; // 30M
try {
mDiskLruCache = DiskLruCache.open(directory, appVersion, valueCount, maxSize);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Bitmap getBitmap(String key) {
try {
DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
if (snapShot != null) {
InputStream is = snapShot.getInputStream(0);
Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public void setBitmap(String key, Bitmap bitmap) {
try {
DiskLruCache.Editor editor = mDiskLruCache.edit(key);
if (editor != null) {
editor.commit();
} else {
editor.abort();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** 双缓存策略 */
public class DoubleCache implements ImageCache {
private MemoryCache mMemoryCache;
private DiskCache mDiskCache;
public DoubleCache() {
mMemoryCache = new MemoryCache();
mDiskCache = new DiskCache();
}
@Override
public Bitmap getBitmap(String key) {
Bitmap bitmap = mMemoryCache.getBitmap(key);
if (bitmap != null) {
return bitmap;
}
return mDiskCache.getBitmap(key);
}
@Override
public void setBitmap(String key, Bitmap bitmap) {
mMemoryCache.setBitmap(key, bitmap);
mDiskCache.setBitmap(key, bitmap);
}
}
public class ImageLoader {
/** 默认使用内存缓存的策略 */
private ImageCache mImageCache = new MemoryCache();
/** 修改策略的接口 */
public void setImageCache(ImageCache imageCacheStrategy) {
mImageCache = imageCacheStrategy;
}
/** 对外调用,使用展示网络图片 */
public void display(final String url, ImageView imageView) {
Bitmap bitmap = mImageCache.getBitmap(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
downloadBitmap(url, imageView);
}
}
private void downloadBitmap(final String url, final ImageView imageView) {
Downloader downloader = new BitmapDownloader();
downloader.download(url, new Downloader.Callback<Bitmap>() {
@Override
public void success(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
@Override
public void failed() {
}
});
}
}
——-下载职责分离——
public interface Downloader<X> {
void download(String url, Callback<X> callback);
interface Callback<Y> {
void success(Y y);
void failed();
}
}
public class BitmapDownloader implements Downloader<Bitmap> {
@Override
public void download(String url, final Callback<Bitmap> callback) {
OkGo.<Bitmap>get(url)
.tag(this)
.execute(new BitmapCallback() {
@Override
public void onSuccess(Response<Bitmap> response) {
callback.success(response.body());
}
});
}
}
public class StringDownLoader implements Downloader<String> {
@Override
public void download(String url, final Callback<String> callback) {
OkGo.<String>get(url)
.tag(this)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
callback.success(response.body());
}
});
}
}
——–最后呈现给客户端———–
public class ClientActivity extends Activity {
private ImageView mImageView;
private ImageLoader mImageLoader;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
mImageView = (ImageView) findViewById(R.id.image);
mImageLoader = new ImageLoader();
/* 采用默认的内存缓存策略 */
mImageLoader.display("http://127.0.0.1:8080/wahaha.png", mImageView);
/* 采用内存缓存策略 */
mImageLoader.setImageCache(new MemoryCache());
mImageLoader.display("http://127.0.0.1:8080/wahaha.png", mImageView);
/* 采用硬盘缓存策略 */
mImageLoader.setImageCache(new DiskCache());
mImageLoader.display("http://127.0.0.1:8080/wahaha.png", mImageView);
/* 采用双缓存策略 */
mImageLoader.setImageCache(new DoubleCache());
mImageLoader.display("http://127.0.0.1:8080/wahaha.png", mImageView);
}
}
如上为采用“开闭原则”,配合策略模式的小示例!