作为程序员也有一段时间,直觉感觉到自己遇到了瓶颈,每次写代码,都会想怎么去设计,让代码更合理,更容易扩展,苦于没有理论的支持,虽然代码看起来还行,但是终究是纸老虎。于是觉得苦心研读设计模式。也算是记录一下心得,顺便提升一下博客的逼格。哈哈
我们代码设计一般都遵循六大设计原则,其一便是单一职责原则。单一职责原则,英文是:Single Responsibility Principle,简称SRP。
那么,什么是单一职责原则呢?
SRP的英文解释是:There shoud never be more then one reason for a class to change
即:有且仅有一个原因引起类的变化。
这句话其实有些抽象,什么叫有且仅有一个原因?下面看代码。
案例一:
我们经常会遇到对用户进行操作。那么就举个修改用户信息的例子。
import org.apache.catalina.User;
/**
* @author <a href="mailto:934804229@qq.com">934804229</a>
* @version 2.0,
* @param
* @return
* @description 用户信息接口类
*/
public interface IUserInfo {
void setUserId(String userId) ;
void getUserId(String userId);
void setUserName(String name);
void getUserName(String name);
void changeUserName(String userId,String name);
}
上面这个代码,我相信很多人一眼就能看出来哪里有问题了。
是的,这个接口设计的有问题,他违反了单一职责原则。getter和setter属于业务对象范畴,而changeUserName()则属于业务逻辑范畴,那么引起类变化的原因就有两个了。
那么我们怎么改呢?
我们可以把业务对象(IUserBO)和业务逻辑(IUserBzi)分别抽出来。
/**
* @author <a href="mailto:934804229@qq.com">934804229</a>
* @version 2.0,
* @param
* @return
* @description 用户信息(业务对象)接口类
*/
public interface IUserBO {
void setUserId(String userId) ;
void getUserId(String userId);
void setUserName(String name);
void getUserName(String name);
}
/**
* @author <a href="mailto:934804229@qq.com">934804229</a>
* @version 2.0,
* @param
* @return
* @description 用户信息(业务逻辑)接口类
*/
public interface IUserBzi {
void changeUserName(String userId,String name);
}
实现类:
你看,现在是不是IUserBO和IUserBzi各施其职?
那么有人可能会问,为啥又用用一个实现类呢?两个不是更好吗?
主要原因有二:
1、是我们是面向接口编程,我们暴露给外面的是接口,所以实现类一个也是可以的。
2、如果分为两个实现类,然后在聚合在一个userInfo里,就变成了强耦合,违反了解耦思想。
-----------------------------------------------------------------华丽的分割线----------------------------------------------------------------------------
案例一,只要是做过开发的,一眼就能看出来,我们不妨来看看下面这个案例。
案例二:
/**
* @author <a href="mailto:934804229@qq.com">934804229</a>
* @version 2.0,
* @param
* @return
* @description 电话类
*/
public interface IPhone {
//拨打电话
void dial(String phoneNumber);
//通话
void chat (Object o);
//挂断
void hangup();
}
这段代码有没有发现有什么问题呢?
其实一般来说这接口设计的已经相当不错了,我们正常研发过程中,也经常这么写。
但是回头想想,dial()和hangup()是通讯,而chat()是数据传输,这是两个不同的东西,那么放在一个接口里,是不是就违反了单一职责原则了呢?
所以我们可以把他们拆分成两个接口:IConnectionManager(通讯接口)和IDataManager(数据接口)
/**
* @author <a href="mailto:934804229@qq.com">934804229</a>
* @version 2.0,
* @param
* @return
* @description 电话(通讯)类
*/
public interface IConnectionManager {
//拨打电话
void dial(String phoneNumber);
//挂断
void hangup();
}
/**
* @author <a href="mailto:934804229@qq.com">934804229</a>
* @version 2.0,
* @param
* @return
* @description 电话(数据)类
*/
public interface IDataManager {
//通话
void chat (Object o);
}
实现类:
那么讲了那么多,单一职责原则究竟有什么好处呢?
1、类的复杂度降低,每个类职责明确。
2、提高了可读性
3、便于维护,无论是我们自己还是后面的萝卜,都能很快接手。
4、提高扩展性。单一职责如果设计的好,那么会大大降低代码风险,例如IDataManager接口修改,只有其对应的实现类收到影响,其它接口不会受到影响。
在这里也要感谢设计之禅书籍,学到很多。