您的位置:首页 > 移动开发 > Android开发

从ImageLoader来理解设计原则

2016-06-27 08:19 441 查看
本文整理自 android 源码设计模式

程序为了 高效 易读,对于 机器 和 人类 都有一个好的沟通.于是我们选择 中庸之道.这样对于机器来书,执行效率还比较高,对于人类理解来说,更易懂.

设计遵循的原则呢,根据人们在写代码的过程中,总结出来的经验,大的原则有六种.

单一职责 S

开闭原则O

里氏替换原则L

依赖倒置原则I

接口隔离D

迪米特(Least knowledge最少知识原则)


前5大原则正好缩写 SOLID—立体的 可靠的.有了这些原则可以说,程序就可靠了就靠谱了

加上第六大原则.第六大原则呢,是般若智慧,般若无知无所不知.

一切始于需求: 小二 来一份蛋炒饭,不要饭…

来一个 能缓存能下载图片的东东—

于是我们要去准备了,蛋和饭 本来看着在一个盘子里,可实际他们是两种不同的口味

我们要的东西首先能下载,其次还能缓存.这明明是两个要求好吗.两种口味(实际中,就算顾客要份炒饭,你也得问清楚,客官,你是要蛋炒饭还是要鸡蛋炒饭)

于是我们引出了我们第一个原则——-单一职责

我们写两个类—一个ImageLoader类,一个Cache类

第二次,顾客说,老板,蛋炒饭加点葱花!__开闭原则—一盘蛋炒饭得到了扩展———-可以除了主要的 蛋 和 饭 的原材料 功能外,我们可以根据自己口味 放 葱蒜青菜等—毕竟 可扩展是框架最重要的特性之一

那么开闭说的是什么呢?软件中的对象(类,模块,方法—)应该对于扩展是开放的,但,对于修改是封闭的.那么我们用什么方法来做到这一点呢?——抽象!

开闭原则 还有一个 孪生兄弟 叫做 里氏替换原则—所有引用基类的地方必须能透明的使用其子类的对象—说人话就是:只要父类能出现的地方,子类就能出现—-于是父类通常是个抽象的类或者接口(对于修改关闭)子类是具体的功能(对于扩展开放)

第四个原则,依赖倒置.在java中,模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生 的.

比如缓存,我们依赖于一个接口,而不是依赖于 具体的实现(比如硬盘缓存或是内存缓存)

第五,接口隔离原则—-目的解耦,更容易重构,更改和重新部署. 功能提供给用户,具体怎么实现,用户完全不知道!隔离实现类的细节,也使得我们将庞大的接口拆分到更细的粒度的接口中

第六 迪米特原则——只与直接的朋友通信.依赖的类少点,让自己变的更独立!



public interface ImageCache {
public void put(String url, Bitmap bitmap);
public Bitmap get(String url);
}


public class ImageLoader {
// 图片缓存
ImageCache  mMemoryCache = new MemoryCache();
//线程池,线程数量为cpu的数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

//注入缓存实现
public void setImageCache(ImageCache imageCache){
mMemoryCache = imageCache;
Log.e("ImageLoader","setImageCache");
}

public  void displayImage(String imageUrl,ImageView imageView){
Bitmap bitmap = mMemoryCache.get(imageUrl);
if (bitmap!=null){
imageView.setImageBitmap(bitmap);
}
//如果没缓存,提交到线程池下载图片
submitLoadRequest(imageUrl,imageView);

}

private void submitLoadRequest(final String imageUrl, final ImageView imageView) {
imageView.setTag(imageUrl);
Log.e("ImageLoader","submitLoadRequest");
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Log.e("ImageLoader", "submitLoadRequest2--");
Bitmap bitmap = downloadImage(imageUrl);
if (bitmap == null) {
return;
}
if (imageView.getTag().equals(imageUrl)) {
imageView.setImageBitmap(bitmap);
}
mMemoryCache.put(imageUrl, bitmap);
Log.e("ImageLoader", "submitLoadRequest");
}
});
}

/**
* 这个耗时操作开一个线程去完成这个任务
* @param imageUrl
* @return
*/
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
Log.e("ImageLoader","downloadImage1");
URL url = new URL(imageUrl);
Log.e("ImageLoader","downloadImage2");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Log.e("ImageLoader","downloadImage3");
bitmap = BitmapFactory.decodeStream(connection.getInputStream());
Log.e("ImageLoader","downloadImage");
connection.disconnect();
} catch (Exception e) {
Log.e("ImageLoadereee",e.toString());
e.printStackTrace();
}

return bitmap;
}
}


public class MemoryCache implements ImageCache {

private LruCache<String ,Bitmap> mMemeryCache ;
public MemoryCache(){
// // TODO: 2016/6/22 初始化Lru 缓存
initMemoryCache();
}

/**
* 自我感觉 这个类可以 也可以提供个接口给用户,让用户自己定义
*/
private void initMemoryCache() {
// 计算可使用的最大内存
final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);

//取 四分之一的可用内存作为缓存

final int cacheSize = maxMemory/4;

mMemeryCache = new LruCache<String, Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight()/1024;//计算方式有两种
}
};
}

@Override
public void put(String url, Bitmap bitmap) {
mMemeryCache.put(url,bitmap);
}

@Override
public Bitmap get(String url) {
return mMemeryCache.get(url);
}
}


public class DoubleCache implements ImageCache {

ImageCache mMemoryCache = new MemoryCache();
ImageCache mDiskCache = new DiskCache();

/*
将图片缓存到内存和sd卡中
*/
@Override
public void put(String url, Bitmap bitmap) {
mMemoryCache.put(url, bitmap);
mDiskCache.put(url, bitmap);
}

/*
先从内存中读取图片,如果没有,再从sd 卡中获取
*/
@Override
public Bitmap get(String url) {
Bitmap bitmap = mMemoryCache.get(url);
if (bitmap == null) {
bitmap = mDiskCache.get(url);

}
return bitmap;
}
}


public class DiskCache implements ImageCache {
@Override
public void put(String url, Bitmap bitmap) {
// 将bitmap 写入文件
}

@Override
public Bitmap get(String url) {
return null;//从本地文件获取该图片
}

}


如果这些类都写在一个类中,对于以后的维护工作怎么做?为什么拆开呢?

更详细的可以看一下 书中 的精彩介绍android 源码设计模式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 设计模式