面向对象的六大原则(一)——单一职责原则(切合Android,ImageLoader)

来源:互联网 发布:慧聪自动发布软件 编辑:程序博客网 时间:2024/06/05 11:59

阅读《Android源码设计模式解析用于实战》后的记录

一:单一职责原则(Single Responsibility Principle)

顾名思义,就一个类而言,应该仅有一个引起它变化的原因。简单的说,一个类中应该是一组相关性很高的函数、数据的封装。    以图片加载器ImageLoader作为示例。面向对象设计,那么就必须考虑到可扩展性、灵活性。    需求:实现图片加载,并且要将图片缓存起来。问题代码一:
/** * 图片加载类 */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 bitmap) {                return bitmap.getRowBytes() * bitmap.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);          }       });    }    public  Bitmap downloadImage(String imageUrl) {        Bitmap bitmap = null;        try {          URL url = newURL(imageUrl);            final HttpURLConnection conn = (HttpURLConnection)                             url.openConnection();            bitmap = BitmapFactory.decodeStream(conn.getInputStream());            conn.disconnect();        } catch (Exception e) {            e.printStackTrace();        }        return bitmap;    }}

这个ImageLoader.java虽然实现了基本功能,但是程序的耦合性太强,无扩展性,无灵活性。所有的功能都写在一个类里怎么行呢,这样随着功能的增多,ImageLoader类会越来越大,代码也越来越复杂,图片加载系统就越来越脆弱。用单一职责原则进行第一步优化:

这里写图片描述

ImageLoader代码修改如下:

/** * 图片加载类 */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);            }        });     }    public  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;    }}   

并且添加了一个ImageCache类用于处理图片缓存,具体代码如下:

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 bitmap) {                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;           }        };     }    public void put(String url, Bitmap bitmap) {        mImageCache.put(url, bitmap) ;    }    public Bitmap get(String url) {        return mImageCache.get(url) ;    }}

将ImageLoader一拆为二,ImageLoader只负责图片加载的逻辑,而ImageCache只负责处理图片缓存的逻辑,这样ImageLoader的代码量变少了,职责也清晰了,当与缓存相关的逻辑需要改变时,不需要修改ImageLoader类,而图片加载的逻辑需要修改时也不会影响到缓存处理逻辑。

如何划分一个类、一个函数的职责,每个人都有自己的看法,这需要根据个人经验、具体的业务逻辑而定。但是,它也有一些基本的指导原则,例如,两个完全不一样的功能就不应该放在一个类中。一个类中应该是一组相关性很高的函数、数据的封装。工程师可以不断地审视自己的代码,根据具体的业务、功能对类进行相应的拆分,我想这会是你优化代码迈出的第一步。

0 0
原创粉丝点击