面向对象的六大原则之 —— 迪米特原则

学习了何红辉、关爱民写的《Android设计模式》,对于面向对象的六大原则有进一步的理解,特此根据自己的理解记录总结一下

什么是迪米特原则

也称为最少知识原则,意思就是一个对象应该对其他对象有最少的了解,其实就是解耦合,两个类之间的关系分离的越细越好,比如面向对象的六大原则之 —— 单一原则中讲的,Imageloader类,它需要缓存,然而缓存ImageCache的具体实现,ImageLoader是不知道的。

我们打个比方,你卖肾跟iphone代理商买了一台 Iphone100 ,结果用了几天,泥马坏了,你是不是应该把手机给回代理商去保修,然而你是不需要知道,人家是怎么保修的,你只需要把手机给回代理商,让人家去保修,其他的你一概不管,保修不好就还肾,就这么简单。

实际运用一下,我们原本的ImageLoader类是直接跟内存缓存打交道的

import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.util.LruCache;  
import android.widget.ImageView;  
  
import java.io.IOException;  
import java.net.HttpURLConnection;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
/** 
 * Created by Administrator on 2016/3/1. 
 */  
public class ImageLoader {  
  
    public ImageLoader() {  
    }  
  
    //图片缓存类  
    ImageCache imageCache=new ImageCache();  
    //线程池,线城数量为cpu的数量  
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());  
  
    /** 
     * 显示图片 
     * @param url 图片的url 
     * @param imageView 要显示的view 
     */  
    public void displayImage(final String url, final ImageView imageView) {  
        Bitmap bitmap=imageCache.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);  
                }  
                imageCache.put(url, bitmap);  
            }  
        });  
    }  
    /** 
     * 下載圖片 
     * @param imageUrl 网络图片地址 
     * @return 返回bitmap对象 
     */  
    public Bitmap downloadImage(String imageUrl) {  
        Bitmap bitmap = null;  
        try {  
            URL url = new URL(imageUrl);  
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
            bitmap = BitmapFactory.decodeStream(conn.getInputStream());  
            conn.disconnect();  
        } catch (MalformedURLException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return bitmap;  
    }  
}  


ImageCache类

import android.graphics.Bitmap;  
import android.util.LruCache;  
  
/** 
 * Created by Administrator on 2016/3/1. 
 */  
public class ImageCache {  
  
    public ImageCache() {  
        //初始化图片缓存  
        initImageCache();  
    }  
  
    //图片缓存类  
    LruCache<String, Bitmap> imageCache;  
  
    /** 
     * 初始化缓存 
     */  
    private void initImageCache() {  
        //计算可使用的最大内存  
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
        //只用最大内存的四分之一作为缓存大小  
        int cacheSize = maxMemory / 4;  
        imageCache = new LruCache<String, Bitmap>(cacheSize) {  
            @Override  
            protected int sizeOf(String key, Bitmap value) {  
                return value.getRowBytes() * value.getHeight() / 1024;  
            }  
        };  
    }  
  
    /** 
     * 添加缓存 
     * 
     * @param url    缓存的图片url作为缓存的key 
     * @param bitmap 缓存的bitmap 
     */  
    public void put(String url, Bitmap bitmap) {  
        imageCache.put(url, bitmap);  
    }  
  
    /** 
     * 获取缓存的图片 
     * 
     * @param url 
     * @return 
     */  
    public Bitmap get(String url) {  
        Bitmap bitmap = null;  
        bitmap = imageCache.get(url);  
        return bitmap;  
    }  
}  

你会发现,我们的Imageloader在实现缓存的时候,就需要直接跟缓存类ImageCache打交道。

我们想一下,给个代理商的类

这个代理商类,我们就直接命名为ImageCache,所以,ImageCache现在的内容如下

import android.graphics.Bitmap;  
  
/** 
 * Created by Administrator on 2016/3/1. 
 */  
public interface ImageCache {  
    /** 
     * 添加缓存 
     * @param url    缓存的图片url作为缓存的key 
     * @param bitmap 缓存的bitmap 
     */  
    public void put(String url, Bitmap bitmap);  
  
    /** 
     * 获取缓存的图片 
     * @param url 
     * @return 
     */  
    public Bitmap get(String url);  
}  

ImageCache只需要作为你的iphone手机跟厂商的桥梁,而现在的厂商是ImageLoader,它直接跟代理商ImageCache打交道

import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.widget.ImageView;  
  
import java.io.IOException;  
import java.net.HttpURLConnection;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
/** 
 * Created by Administrator on 2016/3/1. 
 */  
public class ImageLoader {  
  
    public ImageLoader() {  
    }  
  
    //默认使用内存缓存  
    ImageCache imageCache=new MemoryCache();  
  
    //线程池,线城数量为cpu的数量  
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());  
  
    /** 
     * 设置要使用哪种缓存 
     * @param imageCache 缓存类 
     */  
    public void setImageCache(ImageCache imageCache) {  
        this.imageCache = imageCache;  
    }  
  
    /** 
     * 显示图片 
     * @param url 图片的url 
     * @param imageView 要显示的view 
     */  
    public void displayImage(final String url, final ImageView imageView) {  
        Bitmap bitmap=imageCache.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);  
                }  
                //添加到缓存  
                imageCache.put(url, bitmap);  
            }  
        });  
    }  
  
    /** 
     * 下載圖片 
     * @param imageUrl 网络图片地址 
     * @return 返回bitmap对象 
     */  
    public Bitmap downloadImage(String imageUrl) {  
        Bitmap bitmap = null;  
        try {  
            URL url = new URL(imageUrl);  
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
            bitmap = BitmapFactory.decodeStream(conn.getInputStream());  
            conn.disconnect();  
        } catch (MalformedURLException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return bitmap;  
    }  
}  

这个时候,我们只需要建立一个实现了ImageCache接口的实现类,也就是买了iphone100的你自己

import android.graphics.Bitmap;  
import android.util.LruCache;  
  
/** 
 * Created by Administrator on 2016/3/1. 
 */  
public class MemoryCache implements ImageCache{  
  
    public MemoryCache() {  
        //初始化图片缓存  
        initImageCache();  
    }  
  
    //图片缓存类  
    LruCache<String, Bitmap> memoryCache;  
  
    /** 
     * 初始化缓存 
     */  
    private void initImageCache() {  
        //计算可使用的最大内存  
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
        //只用最大内存的四分之一作为缓存大小  
        int cacheSize = maxMemory / 4;  
        memoryCache = new LruCache<String, Bitmap>(cacheSize) {  
            @Override  
            protected int sizeOf(String key, Bitmap value) {  
                return value.getRowBytes() * value.getHeight() / 1024;  
            }  
        };  
    }  
  
    /** 
     * 添加缓存 
     * 
     * @param url    缓存的图片url作为缓存的key 
     * @param bitmap 缓存的bitmap 
     */  
    public void put(String url, Bitmap bitmap) {  
        memoryCache.put(url, bitmap);  
    }  
  
    /** 
     * 获取缓存的图片 
     * 
     * @param url 
     * @return 
     */  
    public Bitmap get(String url) {  
        Bitmap bitmap = null;  
        bitmap = memoryCache.get(url);  
        return bitmap;  
    }  
}  

这样,我们就实现了迪米特原则,一个对象应该对其他对象有最少的了解,即两个类之间没有直接关系,也就降低了耦合度,在需要添加一个卖肾买iphone的人的时候,只需要实现ImageCache接口,就能实现保修。

对于上面的解释你可能会比较迷糊,我专业点解释一下,其实就是,我们这个ImageLoader图片加载器原先在实现缓存的时候,是直接跟缓存类ImageCache打交道的,也就说明了,一但我们需要添加新的缓存方式,我们就需要更改ImageLoader里面的代码,这样明显的说明了,两个类之间是有直接关系的,而迪米特原则就是,不要有直接关系,或者说,关系越小越好,所以,我们拆开来,搞了一个中间的接口ImageCache,而真正的实现缓存的MemoryCache内存缓存类,实现了ImageCache接口,在ImageLoader中,我们只需要使用ImageCache接口就行,这样,用户在使用哪一种缓存的时候,只要实现ImageCache接口就能实现自己想要的缓存方式,而且还不需要修改ImageLoader类里面的代码,只需要通过调用ImageLoader里面的

  1. /** 
  2.      * 设置要使用哪种缓存 
  3.      * @param imageCache 缓存类 
  4.      */  
  5.     public void setImageCache(ImageCache imageCache) {  
  6.         this.imageCache = imageCache;  
  7.     }  
这个方法就能通过依赖注入的方式,选择自己想要使用的缓存方式。

上一篇:《面向对象的六大原则之 —— 接口隔离原则》         


你可能感兴趣的:(设计模式,android,面向对象)