六大设计原则之依赖倒置原则

依赖倒置原则:一种特定的解耦形式,使得高层次模块不依赖低层次模块的实现细节的目的,依赖
被颠倒了。可以这么理解,实现的细节依赖于抽象。那么抽象又是什么呢?可以理解为一种约定好
的规则,在Java语言中,抽象具体指的是接口或抽象类,两者都不能直接被实例化。细节就是实现
类,即实现接口或继承抽象类而产生的类就是细节。其具体的表现为,模块间的依赖不通过细节类
发生,而是通过抽象(接口或者抽象类)发生。
以上都可以理解为面向接口编程或者面向抽象(这里指接口或者抽象类)编程。如果类与类直接直
接依赖于细节,他们之间就有直接的耦合,这样当需求变化时,往往需要同时修改依赖和被依赖者
的代码,这是我们应当避免出现的,原因就是很容易引入新bug,也限制了系统的扩展性能。
还是用第一、二篇中的例子来说明。

public class ImageLoader {
    //内存缓存(直接依赖于细节),MemoryCache类参考上一篇文章
   private MemoryCache mImageCache = new MemoryCache();
    //线程池,线程数量为CUP的数量
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().
            availableProcessors());
    //UI Handler
    Handler mUiHandler = new Handler(Looper.getMainLooper());

    /**
     * 提供外部调用显示图片的函数
     *
     * @param url       图片的路径
     * @param imageview 显示图片的view
     */
    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)) {
                    updateImageview(imageview, bitmap);
                }
                mImageCache.put(url, bitmap);
            }
        });
    }
    //部分代码省略,具体参考《六大设计原则之开闭原则》
}

现在用户觉得内存缓存已经不能满足要求,还需要缓存到sd卡中。如果不用设计模式去实现,我们通
常的做法是:

1.实现一个可以用于sd卡缓存的类DiskCache
2.在ImageLoader中将ImageCache改为DiskCache

但是如果用户的需求再次改变呢?需要双缓存,我们又得改原来的代码,这就相当于ImageLoader
的实现依赖具体细节类ImageCache类或者DiskCache类,或者其他的,这不违反了上一篇的开闭
原则了吗?也违反了本节中的依赖倒置原则。
那么我们可以考虑下把这些具体细节共同的特性抽象出来,我们就可以依赖于这个规则去实现我们
的细节,其实就是依赖于抽象而不是细节。针对于图片缓存,主要是图片缓存的方式(内存、sd卡
或者双缓存),从缓存的地方取出图片这两个功能。暂且不考虑各缓存方式是怎么实现的,我们先
抽象出这两个共性。所以我们建一个图片缓存的接口:

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

在接口中有两个方法,其中一个用于存,一个用于取。
这样ImageLoader类就可以通过注入的方式依赖于这个接口,如下所示

public class ImageLoader {
    //内存缓存,依赖于抽象,并且有一个默认的缓存策略MemoryCache,MemoryCache类参考上一篇文章
    private ImageCache mImageCache = new MemoryCache();
    //线程池,线程数量为CUP的数量
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().
            availableProcessors());
    //UI Handler
    Handler mUiHandler = new Handler(Looper.getMainLooper());

    /**
     * 提供外部调用显示图片的函数
     *
     * @param url       图片的路径
     * @param imageview 显示图片的view
     */
    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)) {
                    updateImageview(imageview, bitmap);
                }
                mImageCache.put(url, bitmap);
            }
        });
    }

    /**
    *设置注入的缓存策略,依赖于对象
    */
    public void setImageCache(ImageCache cache){
        mImageCache = cache;
    }

    //部分代码省略,具体参考《六大设计原则之开闭原则》
}

最后,我们想用哪种缓存策略,只要实现接口ImageCache接口即可,然后通过ImageLoader
对象中的setImageCache()注入即可。这样我们就不需要去更改ImageLoader中的代码了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值