您的位置:首页 > 其它

设计模式笔记—单一职责原则

2018-01-19 22:29 381 查看

单一职责原则

            概念: 英文名称是Single Responsibility Principle,简称SRP.就一个类而言,应该仅有一个引起它变化的原因。意思是当你在设计一个类的时候,应该尽量划分这个类的职责是什么,让它发生改变的因素尽量单一。举例如下:
          
            案例:接口设计         
            未划分之前:
               
public interface IUserInfo {
void setUser(String userID);
String getUserID();
void setPassword(String password);
void setUserName(String unserName);
String getUserName();
boolean changePassword(String oldPassword);
boolean deleteUser();
void mapUser();
boolean addOrg(int orgID);
boolean addRole(int roleID);
}

  可以看出这个接口涉及的很乱,因为没有将用户的属性和用户的行为划分开。应该拆分,把用户的信息抽取成一个
业务对象(Bussiness Object ),把行为抽取成一个业务逻辑类(Business Logic).
划分之后:
          
//负责用户的行为
public interface IUserBiz {
boolean changePassword(String oldPassword);
boolean deleteUser(IUserBO user);
void mapUser(IUserBO user);
boolean addOrg(IUserBO user,int orgID);
boolean addRole(IUserBO user,int roleID);
}

//负责用户的属性
public interface IUserBO {
void setUser(String userID);
String getUserID();
void setPassword(String password);
void setUserName(String unserName);
String getUserName();
}      

public interface IUserInfo extends IUserBiz,IUserBO{
......
}

  调用时:

IUserBiz userInfo=new UserInfo();
//赋值时,就认为它是一个纯粹的实体类
IUserBO userBO=(IUserBO) userInfo;
//执行动作时,就认为是一个业务逻辑类
IUserBiz userBiz=(IUserBiz)userInfo;
userBiz.deleteUser(xx);

  以上把一个接口拆分成两个接口的动作,就是依赖了单一职责原则。再看一个图片加载的案例
未划分之前:

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 iv){
iv.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap=downloadImage(url);
if(bitmap==null){
return;
}
if(iv.getTag().equals(url)){
iv.setImageBitmap(bitmap);
}
mImageCache.put(url,bitmap);
}
});
}
public Bitmap downloadImage(String imageUrl){
Bitmap bitmap=null;
try {
URL url = new URL(imageUrl);
final HttpURLConnection conn= (HttpURLConnection) url.openConnection();
bitmap= BitmapFactory.decodeStream(conn.getInputStream());
}catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
}

          分析:ImageLoader耦合很严重,所有功能都写在一个类里面,这样随着功能的增加,ImageLoader类的代码量会      越来越大,代码也越来越复杂,图片加载系统就变得很脆弱,维护起来就很费力。
划分后

public class ImageLoader2 {
ImageCache mImageCache=new ImageCache();
//线程的数量为CPU的数量
ExecutorService mExecutorService= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public void displayImage(final String url,final ImageView iv){
Bitmap bitmap = mImageCache.get(url);
if(bitmap!=null){
iv.setImageBitmap(bitmap);
return;
}
iv.setTag(url);
mExecutorService.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap=downloadImage(url);
if(bitmap==null){
return;
}
if(iv.getTag().equals(url)){
iv.setImageBitmap(bitmap);
}
mImageCache.put(url,bitmap);
}
});
}
public Bitmap downloadImage(String imageUrl){
Bitmap bitmap=null;
try {
URL url = new URL(imageUrl);
final HttpURLConnection conn= (HttpURLConnection) url.openConnection();
bitmap= BitmapFactory.decodeStream(conn.getInputStream());
}catch (Exception e){
e.printStackTrace();
}
return bitmap;
}
}

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 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);
}
}

  分析:将ImageLoader一拆为二,ImageLoader2只负责图片加载的逻辑,而ImageCache只负责处理图片缓存的逻辑,这样ImageLoader的代码量少了,职责也清晰了。
如何来划分一个类,一个接口,一个函数的职责?每个人都有自己的看法,这个需要根据个人经验,具体的业务逻辑而定。

但是它有一些基本的指导原则,比如,两个完全不一样的功能就不应该放在一个类中。一个类中应该是一组相关性很高的函数,

数据的封装。

优点:
1) 类的复杂性降低,实现什么原则都有清晰明确的定义。
2)可读性提高,复杂性降低。
3)可维护性提高。
4)变更引起的风险降低,变更是必不可少的,如果单一职责做的好,产生的影响就会较小。
总结:本文案例占很大篇幅,主要想表明单一职责原则重点在职责的划分上,划分好职责,会给你减少很多负担。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: