面向对象--单一职责原则和开闭原则学习(简易ImageLoader)

一、概述

这篇是读《Android源码设计模式解析与实战》的第一篇记录,今天学习了面向对象六大原则中的其二:单一职责原则和开闭原则。单一职责原则简单来说一个类只实现一个功能;开闭原则则是对于扩展是开放的,对于修改是关闭的。这些原则都是用来优化代码的。

二、简易ImageLoader实现

下面通过一个简单的ImageLoader来说明编码过程中的以上两个原则。
首先,一个ImageLoader主要分为两部分,一部分为图片加载,另一部分为图片缓存,这就可以提示我们可以将功能分为两个类分别实现(单一职责原则)。同时,缓存可分为内存缓存、存储缓存以及双缓存,甚至以后还可能有什么缓存技术,但其作用都是取出和存入两项功能,为了方便扩展,我们将取出和存入抽象出一个接口来实现(开闭原则)。

三、代码展示

缓存接口:

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

内存缓存接口实现:

public class MemoryCache implements ImageCache {

    LruCache<String, Bitmap> mMemoryCache;

    public MemoryCache() {
        initMemoryCache();
    }

    private void initMemoryCache() {
        // 计算可使用的最大内存,单位KB
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        // 通常取四分之一的可用内存作为缓存
        final int cacheSize = maxMemory / 4;
        mMemoryCache = 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) {
        mMemoryCache.put(url, bitmap);
    }

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

存储缓存接口实现:

public class DiskCache implements ImageCache {

    private static final String cacheDir = "sdcard/cache/";

    @Override
    public void put(String url, Bitmap bitmap) {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(cacheDir + url);
            // 将图片进行压缩
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public Bitmap get(String url) {
        return BitmapFactory.decodeFile(cacheDir + url);
    }
}

双缓存接口实现:

public class DoubleCache implements ImageCache {
    ImageCache mMemoryCache = new MemoryCache();
    ImageCache mDiskCache = new DiskCache();

    @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 ImageLoader {
    ImageCache mImageCache = new MemoryCache();
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    // 注入缓存实现
    public void setImageCache(ImageCache imageCache) {
        this.mImageCache = imageCache;
    }

    public void displayImage(String url, ImageView imageView) {
        Bitmap bitmap = mImageCache.get(url);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
            return;
        }
    }

    private void submitLoadRequest(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来学习单一职责原则和开闭原则的过程,在平时功能设计和编码时都要时刻注意。项目中使用的ImageLoader会更为复杂,有兴趣的可参考一些优秀的第三方开源库源码进行学习。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值