前言
开闭原则的英文全称是Open Close Principle,缩写是OCP,它是Java世界里最基础的设计原则,它指导我们如何建立一个稳定,灵活的系统。
开闭原则的定义
软件中的对象(类,模块,函数等)应该对于扩展是开放的,但是,对于修改是封闭的。
范例
实现图片加载缓存功能
public class ImageLoader{
//图片缓存
ImageCache mImageCache=new MemoryCache();
//线程池,线程数量为CPU的数量
ExecutorService mExecutorService
=Excutors.newFixedThreadPool(Runtime.getRuntim().availableProcessors());
//注入缓存实现
public void setImageCache(ImageCache cache){
mImageCache=cache;
}
public void displayImage(String imageUrl,ImageView imageView){
Bitmap bitmap=mImageCache.get(imageUrl);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
//图片没缓存,提交到线程池中下载图片
sunmitLoadRequest(imageUrl,imageView);
}
private void submitLoadRequest(final String imageUrl,final ImageView imageView){
imageView.setTag(imageUrl);
mExcutorService.submit(new Runnable() {
@Override
public void run(){
Bitmap bitmap=downloadImage(imageUrl);
if(bitmap==null){
return;
}
if(imageView.getTag().equals(imageUrl));
imageView.setImageBitmap(bitmap);
}
mImageCache.put(imageUrl,bitmap);
}
});
}
public Bitmap downloadImage(String imageUrl) {
Bitmap bitmap=null;
try{
URL url=new URL(imageUrl);
final HttpURLConnection conn=(HttpURLConnection) url.openConnection();
bitmap=BitmapFactory.decodeStream(coon.getInputStream());
conn.disconnect();
}catch(Exception e) {
e.printStackTrace();
}
return bitmap;
}
}
需要注意的是这里的ImageCache,我把它提取为一个图片缓存接口,接口声明如下:
public interface ImageCache{
public Bitmap get(String url);
public void put(String url,Bitmap bmp);
}
ImageCache接口简单定义了获取,缓存图片两个函数,缓存的key是图片的url,值是图片本身。内存缓存,SD卡缓存,双缓存都实现了该接口,我们看看这几个缓存实现:
//内存缓存MemoryCache
public class MemoryCache implements ImageCache{
private LruCache<String,Bitmap> mMemeryCache;
public MemoryCahe(){
//初始化LRU缓存
}
@Override
public Bitmap get(String url){
return mMemeryCache.get(url);
}
@Override
public void put(String url,Bitmap bmp){
mMemeryCache.put(url,bmp);
}
}
//SD卡缓存DiskCache类
public class DiskCache implements ImageCache{
@Override
public Bitmap get(String url){
return null;//从本地文件中获取该图片
}
@Override
public void put(String url,Bitmap bmp){
//将Bitmap写入文件中
}
}
双缓存DoubleCache类
public class DoubleCache implements ImageCache{
ImageCache mMemoryCache=new MemoryCache();
ImageCache mDiskCache=new DiskCache();
//先从内存中获取图片,如果没有,再从SD卡中获取
public Bitmap get(String url) {
Bitmap bitmap=mMemoryCache.get(url);
}
return bitmap;
}
//将图片缓存到内存和SD卡中
public void put(String url,Bitmap bmp) {
mMemoryCache.put(url,bmp);
mDiskCache.put(url,bmp);
}
}
细心的读者可能发现了,ImageLoader里有一个setImageCache(ImageCache cache)函数,用户可以通过该函数设置缓存实现,也就是通常说的依赖注入。下面就看看用户是如何设置缓存实现的:
ImageLoader imageLoder=new ImageLoader();
//使用内存缓存
imageLoader.setImageCache(new MemoryCache());
//使用SD卡缓存
imageLoader.setImageCache(new DiskCache());
//使用双缓存
imageLoader.setImageCache(new DoubleCache());
//使用自定义缓存
imgeLoader.setImageCache(new ImageCache(){
@Override
public void put(String url,Bitmap bmp){
//缓存图片
}
@Override
public Bitmap get(String url){
return null;//从缓存中获取图片
}
});
在上述代码中,通过setImageCache(ImageCache cache)方法注入不同的缓存实现,这样不仅能够使ImageLoader更简单,健壮,也使得ImgeLoader的可扩展性和灵活性更高。MemoryCache,DiskCache,DoubleCache缓存图片的具体实现完全不一样,但是它们都有一个特点就是都实现了ImageCache接口。
当用户需要自定义实现缓存策略时,只需要新建一个实现ImageCache接口的类,然后构造该类的对象,并且通过setImageCache(ImageCache cache)注入到ImageLoader,这样ImageLoader就实现千变万化的缓存策略,且扩展这些缓存策略并不会导致ImageLoader类的修改。
总结
开闭原则指导我们,当软件需要变化时,应该尽量通过扩展的方式实现变化,而不是通过修改已有的代码来实现。