美文网首页
面向对象六大原则之单一职责原则

面向对象六大原则之单一职责原则

作者: TodoCoder | 来源:发表于2017-06-09 10:42 被阅读0次

    前言

    从开始接触面向对象开始就有对面向对象原则的了解,到目前为止也多次看到,可每次看到的时候,都有种似曾相识却又惊叹无比的感觉,这样的感觉明显是不对的,学完一些知识应该是融汇贯通于你的思想之中,然后穿过你的身体,穿过你的灵魂再展现出来,所以我们要躬行于知识的沃土之上,让那些让规律,想法,知识,真正能穿过我们的灵魂,我们的身体,然后再表达出来,基于此,我也想记录一下我的所学,所知!

    定义

    单一职责原则的英文名称是 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类即可,但此类的扩展灵活性也有所欠缺(此处涉及到开面向对象的另一个原则-开闭原则)

    单一职责原则,主要就是单一两个字,也就是说 多个不一样的功能不应该放到一个类中,一个类应该是一组相关性很高的函数、数据的封装。

    相关文章

      网友评论

          本文标题:面向对象六大原则之单一职责原则

          本文链接:https://www.haomeiwen.com/subject/ncyxqxtx.html