前言
从开始接触面向对象开始就有对面向对象原则的了解,到目前为止也多次看到,可每次看到的时候,都有种似曾相识却又惊叹无比的感觉,这样的感觉明显是不对的,学完一些知识应该是融汇贯通于你的思想之中,然后穿过你的身体,穿过你的灵魂再展现出来,所以我们要躬行于知识的沃土之上,让那些让规律,想法,知识,真正能穿过我们的灵魂,我们的身体,然后再表达出来,基于此,我也想记录一下我的所学,所知!
定义
单一职责原则的英文名称是 Single Responsibility Principle,简称SRP,它的定义是:就一个类而言,应该仅有一个引起它变化的原因。也就是说,一个类中应该是一组相关性很高的函数、数据的封装。
应用
举个栗子
比如这样一个需求,写一个图片加载类,实现图片加载,并且要将图片缓存起来。
实现如下:
/**
* 图片加载类
*/
public class ImageLoader {
//图片缓存
LruCache<String,Bitmap> mImageCache;
//线程池,线程数量为CPU的数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());
public ImageLoader(){
initImageCache();
}
private void initImageCache() {
//计算可使用的最大内存
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
//取四分之一的可用内存作为缓存
final int cacheSize = maxMemory / 4;
mImageCache = new LruCache<String,Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
}
public void displayImage(final String url, final ImageView imageView) {
imageView.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(url);
if (bitmap == null) {
return;
}
if (imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
}
mImageCache.put(url,bitmap);
}
});
}
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}
我们来分析一下这个类,功能上是没有问题的,但把缓存功能的逻辑也杂糅到图片加载类中,这明显不符合单一职责原则,更不要说扩展性、灵活性了,这样随着功能的增加,ImageLoader类只会越来越复杂。
那我们考虑一下怎么解耦?
那我们想一下,如果把图片缓存相关代码剥离出去怎么做。
我们可以把上面代码中缓存图片的LruCache对象交给一个专门的图片缓存类处理,类图如下
对应代码如下:
/**
* 图片缓存类
*/
public class ImageCache {
//图片LRU缓存
LruCache<String,Bitmap> mImageCache;
public ImageCache() {
initImageCache();
}
private void initImageCache() {
//计算可使用的最大内存
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
//取四分之一的可用内存作为缓存
final int cacheSize = maxMemory / 4;
mImageCache = new LruCache<String,Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
}
};
}
public void put (String url,Bitmap bitmap) {
mImageCache.put(url,bitmap);
}
public Bitmap get(String url) {
return mImageCache.get(url);
}
}
/**
* 图片加载类
*/
public class ImageLoader {
//图片缓存
ImageCache mImageCache = new ImageCache();
//线程池,线程数量为CPU的数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());
public void displayImage(final String url, final ImageView imageView) {
Bitmap bitmap = mImageCache.get(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
return;
}
imageView.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(url);
if (bitmap == null) {
return;
}
if (imageView.getTag().equals(url)) {
imageView.setImageBitmap(bitmap);
}
mImageCache.put(url,bitmap);
}
});
}
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}
如上述代码,把ImageLoader一拆为二,ImageLoader只负责图片加载的逻辑,ImageCache负责图片处理的逻辑,这样ImageLoader类的代码少了,职责也清晰了,当与缓存相关的需求需要改变时我们只需更改ImageCache类就可以了,当与加载图片需求需要改变时我们只需修改ImageLoader类即可,但此类的扩展灵活性也有所欠缺(此处涉及到开面向对象的另一个原则-开闭原则)
单一职责原则,主要就是单一两个字,也就是说 多个不一样的功能不应该放到一个类中,一个类应该是一组相关性很高的函数、数据的封装。
网友评论