开闭原则
开闭原则——Open Close Principle OCP
定义:软件中的对象(类、函数、模块)应该对于扩展是开放的,但是,对于修改是封闭的。在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会将错误引入原本已经经过测试的代码中,破坏原有系统,因此,当软件需要变化时,我们尽量通过扩展的方式来实现变化。而不是通过修改已有代码来实现。
示例代码:
Android中的图片加载策略分为 缓存策略 磁盘策略 在使用中是比较典型的开闭原则的应用,使用各种各样的缓存策略时不应该修改程序代码,而应该使用扩展的方式去实现
ImageLoader 类
/**
* Describe:图片加载工具类
* 运用开闭原则,通过拓展的方式实现修改与变化,对于源代码只在处理错误的时候才进行修改
* wx on 2016/12/27.
*/
public class ImageLoader {
// TODO:图片缓存
ImageCache mImageCache = new MemoryCache();
// TODO: 线程池
ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// TODO: 注入缓存实现
public void setImageCache(ImageCache imageCache) {
mImageCache = imageCache;
}
public void displayImage(String imageUrl, ImageView mImageView) {
Bitmap bitmap = mImageCache.get(imageUrl);
if (bitmap != null) {
mImageView.setImageBitmap(bitmap);
return;
}
// TODO: 图片没缓存,启动线程下载图片
submitLoadRequest(imageUrl, mImageView);
}
/**
* 下载图片动作
*
* @param imageUrl 图片地址
* @param mImageView 要加载的图片view
*/
private void submitLoadRequest(final String imageUrl, final ImageView mImageView) {
// TODO: 标记设置
mImageView.setTag(imageUrl);
// TODO: 启动线程池执行
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(imageUrl);
if (bitmap == null) {
return;
}
if (mImageView.getTag().equals(imageUrl)) {
mImageView.setImageBitmap(bitmap);
}
// TODO: 缓存图片
mImageCache.put(imageUrl,bitmap);
}
});
}
/**
* 下载图片具体实现
*
* @param imageUrl
* @return
*/
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
return null;
}
return bitmap;
}
}
该类ImageLoader通过setImageCache(ImageCache cache)方法注入不同的缓存实现,可以使得ImageLoader简单健壮。也使得ImageLoader的可拓展性、灵活性更高。
ImageCache 接口
- 该接口抽象了实现缓存的方法 设置缓存和读取缓存的方法
/**
* Describe: 图片缓存接口
* wx on 2016/12/27.
*/
public interface ImageCache {
/**
* 设置图片方法
*
* @param url
* @return
*/
Bitmap get(String url);
/**
* 取出图片方法
*
* @param url 地址
* @param bitmap 存储的图片
*/
void put(String url, Bitmap bitmap);
}
- 内存缓存实现类
/**
* Describe:内存缓存实现类 继承图片缓存接口
* wx on 2016/12/27.
*/
public class MemoryCache implements ImageCache {
// TODO: LRU缓存集合
private LruCache<String, Bitmap> mMemeryCache;
/**
* 初始化内存缓存方法
*/
public MemoryCache() {
}
@Override
public Bitmap get(String url) {
// TODO: 取图片时从集合中根据相应的url从集合中取出
return mMemeryCache.get(url);
}
@Override
public void put(String url, Bitmap bitmap) {
// TODO: 存储图片缓存时放入集合中
mMemeryCache.put(url, bitmap);
}
}
- SD卡缓存实现类
/**
* Describe:磁盘缓存
* wx on 2016/12/27.
*/
public class DiskCache implements ImageCache {
@Override
public Bitmap get(String url) {
// TODO: 从本地文件中获取图片
return null;
}
@Override
public void put(String url, Bitmap bitmap) {
// TODO: 将Bitmap写入到本地文件中
}
}
- 双缓存实现类
/**
* Describe:双缓存类 先从内存中取图片,内存中没有从本地取图片
* wx on 2016/12/27.
*/
public class DoubleCache implements ImageCache {
// TODO: 构造内存缓存
MemoryCache mMemorycache = new MemoryCache();
DiskCache mDiskCache = new DiskCache();
@Override
public Bitmap get(String url) {
Bitmap bitmap = mMemorycache.get(url);
if (bitmap == null) {
bitmap = mDiskCache.get(url);
}
return bitmap;
}
@Override
public void put(String url, Bitmap bitmap) {
// TODO: 将图片缓存到内存和SDcard中
mMemorycache.put(url, bitmap);
mDiskCache.put(url, bitmap);
}
}
总结
开闭原则指导我们,当软件需要变化时,应该尽量通过扩展的方式来实现变化,而不是通过修改已有的代码来实现。