请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

houcx

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 937|回复: 0

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

[复制链接]

222

主题

224

帖子

1123

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1123
发表于 2018-4-25 14:23:52 | 显示全部楼层 |阅读模式
Java 中面向对象编程六大原则:

单一职责原则 英文名称是Single Responsibility Principle,简称SRP

开闭原则 英文全称是Open Close Principle,简称OCP

里氏替换原则 英文全称是Liskov Substitution Principle,简称LSP

依赖倒置原则  英文全称是Dependence Inversion Principle,简称DIP
接口隔离原则 英文全称是InterfaceSegregation Principles,简称ISP
迪米特原则 英文全称为Law of Demeter,简称LOD,也称为最少知识原则(Least Knowledge Principle)




让你的代码更清晰简单——单一职责原则

单一职责原则的英文名称是Single Responsibility Principle,简称SRP。它的定义是:就一个类而言,应该仅有一个引起它变化的原因。简单来说,一个类中应该是一组相关性很高的函数、数据的封装。单一职责的划分界限并不是总是那么清晰,很多时候都是需要靠个人经验来界定。当然,最大的问题就是对职责的定义,什么是类的职责,以及怎么划分类的职责。

下面以项目中实际代码来分析问题,在android app中图片加载是最常见的,于是我们自己动手写一个ImageLoader(图片加载)作为训练项目。如下代码:


[html] view plain copy


  • public class ImageLoader {  
  •     private static ImageLoader Instance = null;  
  •     // 图片缓存  
  •     LruCache<String, Bitmap> mImageCache;  
  •     // 线程池,线程数量为CPU的数量  
  •     ExecutorService mExecutorService = Executors.newFixedThreadPool (Runtime.getRuntime().availableProcessors());  
  •     //在主线程中显示图片  
  •     Handler mHandler = new Handler(){   
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             super.handleMessage(msg);  
  •             ImageView imageView = (ImageView) msg.obj;  
  •             imageView.setImageBitmap((Bitmap) imageView.getTag());  
  •         }  
  •     };  
  •   
  •     public static ImageLoader getInstance(){  
  •         if(Instance == null){  
  •             synchronized (ImageLoader.class) {  
  •                 if(Instance == null) {  
  •                     Instance = new ImageLoader();  
  •                 }  
  •             }  
  •         }  
  •         return Instance;  
  •     }  
  •     private 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) {  
  •                 //Bitmap的每一行所占用的空间数乘以Bitmap的行数  
  •                 return bitmap.getRowBytes() * bitmap.getHeight() / 1024;  
  •             }  
  •         };  
  •     }  
  •   
  •     public  void displayImage(final String url, final ImageView imageView) {  
  •         imageView.setTag(url);  
  •         //先从cache中取图片  
  •         if(mImageCache.get(url)!=null){  
  •             imageView.setImageBitmap(mImageCache.get(url));  
  •             return;  
  •         }  
  •         mExecutorService.submit(new Runnable() {  
  •             @Override  
  •             public  void run() {  
  •                 Bitmap bitmap = downloadImage(url);  
  •                 if (bitmap == null) {  
  •                     return;  
  •                 }  
  •                 if (imageView.getTag().equals(url)) {  
  •                     Message msg = mHandler.obtainMessage();  
  •                     imageView.setTag(bitmap);  
  •                     msg.obj = imageView;  
  •                     mHandler.sendMessage(msg);  
  •                 }  
  •                 mImageCache.put(url, bitmap);  
  •             }  
  •         });  
  •     }  
  •   
  •     public  Bitmap downloadImage(String imageUrl) {  
  •         Bitmap bitmap = null;  
  •         try {  
  •             URL url = new URL(imageUrl);  
  •             HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
  •             conn.setDoInput(true); //允许输入流,即允许下载  
  •             conn.setUseCaches(false); //不使用缓冲  
  •             conn.setRequestMethod("GET"); //使用get请求  
  •             InputStream is = conn.getInputStream();   //获取输入流,此时才真正建立链接  
  •             bitmap = BitmapFactory.decodeStream(is);  
  •             conn.disconnect();  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •         }  
  •         return bitmap;  
  •     }  
  • }  


上面是一个最简单的ImageLoader,在显示图片之前会去判断是否有缓存,但是我们也发现它耦合太严重啦!简直就没有设计可言,更不要说扩展性、灵活性了。所有的功能都写在一个类里,这样随着功能的增多,ImageLoader类会越来越大,代码也越来越复杂,修改起来就是进入hell.

这里我们可以把ImageCahe相关的代码单独拿出来,写成一个单独的类。


[html] view plain copy


  • public class ImageCache {  
  •     // 图片缓存  
  •     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) {  
  •                 //Bitmap的每一行所占用的空间数乘以Bitmap的行数  
  •                 return bitmap.getRowBytes() * bitmap.getHeight() / 1024;  
  •             }  
  •         };  
  •     }  
  •       
  •     public void put(String key,Bitmap value){  
  •         mImageCache.put(key,value);  
  •     }  
  •       
  •     public Bitmap get(String key){  
  •        return mImageCache.get(key);  
  •     }  
  • }  


所以ImageLoader代码需要修改,并且添加了一个ImageCache类用于处理图片缓存,具体代码如下:


[html] view plain copy


  • public class ImageLoader {  
  •     private static ImageLoader Instance = null;  
  •     private ImageCache mImageCache;  
  •     // 线程池,线程数量为CPU的数量  
  •     ExecutorService mExecutorService = Executors.newFixedThreadPool (Runtime.getRuntime().availableProcessors());  
  •     //在主线程中显示图片  
  •     Handler mHandler = new Handler(){  
  •         @Override  
  •         public void handleMessage(Message msg) {  
  •             super.handleMessage(msg);  
  •             ImageView imageView = (ImageView) msg.obj;  
  •             imageView.setImageBitmap((Bitmap) imageView.getTag());  
  •         }  
  •     };  
  •   
  •     public static ImageLoader getInstance(){  
  •         if(Instance == null){  
  •             synchronized (ImageLoader.class) {  
  •                 if(Instance == null) {  
  •                     Instance = new ImageLoader();  
  •                 }  
  •             }  
  •         }  
  •         return Instance;  
  •     }  
  •     private ImageLoader() {  
  •        mImageCache = new ImageCache();  
  •     }  
  •   
  •     public  void displayImage(final String url, final ImageView imageView) {  
  •         imageView.setTag(url);  
  •         //先从cache中取图片  
  •         if(mImageCache.get(url)!=null){  
  •             imageView.setImageBitmap(mImageCache.get(url));  
  •             return;  
  •         }  
  •         mExecutorService.submit(new Runnable() {  
  •             @Override  
  •             public  void run() {  
  •                 Bitmap bitmap = downloadImage(url);  
  •                 if (bitmap == null) {  
  •                     return;  
  •                 }  
  •                 if (imageView.getTag().equals(url)) {  
  •                     Message msg = mHandler.obtainMessage();  
  •                     imageView.setTag(bitmap);  
  •                     msg.obj = imageView;  
  •                     mHandler.sendMessage(msg);  
  •                 }  
  •                 mImageCache.put(url, bitmap);  
  •             }  
  •         });  
  •     }  
  •   
  •     public  Bitmap downloadImage(String imageUrl) {  
  •         Bitmap bitmap = null;  
  •         try {  
  •             URL url = new URL(imageUrl);  
  •             HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
  •             conn.setDoInput(true); //允许输入流,即允许下载  
  •             conn.setUseCaches(false); //不使用缓冲  
  •             conn.setRequestMethod("GET"); //使用get请求  
  •             InputStream is = conn.getInputStream();   //获取输入流,此时才真正建立链接  
  •             bitmap = BitmapFactory.decodeStream(is);  
  •             conn.disconnect();  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •         }  
  •         return bitmap;  
  •     }  
  • }  


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

从上述的例子中我们能够体会到,单一职责所表达出的用意就是“单一”二字。正如上文所说,如何划分一个类、一个函数的职责,每个人都有自己的看法,这需要根据个人经验、具体的业务逻辑而定。但是,它也有一些基本的指导原则,例如,两个完全不一样的功能就不应该放在一个类中。一个类中应该是一组相关性很高的函数、数据的封装。工程师可以不断地审视自己的代码,根据具体的业务、功能对类进行相应的拆分。

代码github地址:点击打开链接


更多精彩Android技术可以关注我们的微信公众号,扫一扫下方的二维码或搜索关注公共号: Android老鸟


来自:https://blog.csdn.net/jo__yang/article/details/52006982

[发帖际遇]: admin 乐于助人,奖励 4 贡献. 幸运榜 / 衰神榜
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|houcx ( 京ICP备15004793号  

GMT+8, 2019-6-26 07:55 , Processed in 0.064738 second(s), 27 queries .

Powered by houcx! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表