单一职责原则(SRP) Single Responsibility Principle

定义:应该有且仅有一个原因引起类的变更。即单一指责原则要求一个借口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,它就负责一件事情。

优点:1.类的复杂性降低,实现什么职责都有清晰明确的定义

            2.可读性提高,复杂性降低,那当然可读性提高了。

            3.可维护性提高,可读性提高,那当然更容易维护了。

            4.变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性,维护性都有非常大的帮助。

例:通常写用户管理都是一个接口 一个实现类

        

<<用户管理UML.vsdx>>


/**

 *

 * @author liang

 * 用户信息管理

 */

public interface IUserInfo {

 

    //设置用户的ID

public void setUserID(String userID);

 

//获得用户的ID

public String getUserID();

 

//设置用户的密码

/** */

public void setPassword(String password);

 

//获得用户的密码

public String getPassword();

 

//设置用户的名字

public void setUserName(String userName);

 

//获得用户的名字

public String getUserName();

 

//修改用户的密码

public boolean changePassword(String oldPassword);

 

//删除用户

public boolean deleteUser();

 

//用户映射

public void mapUser();

}

/**

 *

 * @author liang

 * 用户管理的实现类

 */

public class UserInfo implements IUserInfo{

 

private String userName;

private String userID;

private String password;

 

public void setUserID(String userID) {

this.userID = userID;

}

 

public String getUserID() {

return userID;

}

 

public void setPassword(String password) {

this.password = password;

}

 

public String getPassword() {

return password;

}

 

public void setUserName(String userName) {

this.userName = userName;

}

 

public String getUserName() {

return userName;

}

 

//修改用户密码

public boolean changePassword(String oldPassword){

System.out.println("密码修改成功...");

return true;

}

 

//删除用户

public boolean deleteUser(){

System.out.println("删除用户成功...");

return true;

}

 

//用户映射

public void mapUser()

System.out.println("用户映射成功...");

}

}

/**

 *

 * @author liang

 *业务类调用

 */

public class Client {

 

public static void main(String[] args) {

IUserInfo userInfo = new UserInfo();

userInfo.changePassword("abc");

}

} 





 用户属性和用户行为没有分开是一个严重的错误!应该把用户的信息抽取程一个BO(Business Object业务对象),把行为抽取成一个Biz(Business Logic业务逻辑)

<<修改后用户管理UML.vsdx>>


/**

 *

 * @author liang

 * 用户的业务对象

 */

public interface IUserBO {

 

// 设置用户ID

void setUserID(String userID);

 

// 获取用户ID

String getUserID();

 

// 设置用户密码

void setPassword(String password);

 

// 获得用户密码

String getPassword();

 

// 设置用户姓名

void setUserName(String userName);

 

// 获得用户姓名

String getUserName();

}

/**

 *

 * @author liang

 *用户信息管理

 */

public interface IUserBiz {

 

//修改用户密码

boolean changePassword(String oldPassword);

 

//删除用户

boolean deleteUser();

 

//用户映射

void mapUser();

 

//增加一个组织

boolean addOrg(int orgID);

 

//增加一个角色

boolean addRole(int roleID);

}

/**

 *

 * @author liang

 *

 */

public interface IUserInfo extends IUserBiz,IUserBO{

 

}

/**

 *

 * @author liang

 * 用户管理的实现类

 */

public class UserInfo implements IUserInfo {

 

private String userID;

private String password;

private String userName;

 

public void setUserID(String userID) {

this.userID = userID;

}

 

public String getUserID() {

return userID;

}

 

public void setPassword(String password) {

this.password = password;

}

 

public String getPassword() {

return password;

}

 

public void setUserName(String userName) {

this.userName = userName;

}

 

public String getUserName() {

return userName;

}

 

// 修改用户密码

public boolean changePassword(String oldPassword) {

System.out.println("修改密码成功");

return true;

}

 

// 删除用户

public boolean deleteUser() {

System.out.println("删除成功");

return true;

}

 

// 用户映射

public void mapUser() {

System.out.println("映射成功");

}

 

// 增加一个组织

public boolean addOrg(int orgID) {

System.out.println("增加组织");

return true;

}

 

// 增加一个角色

public boolean addRole(int roleID) {

System.out.println("增加角色");

return true;

}

 

}

/**

 *

 * @author liang

 *业务类调用

 */

public class Client {

 

public static void main(String[] args) {

IUserInfo userInfo = new UserInfo();

//我要复制了,我就认为它是一个纯粹的BO

IUserBO userBO = (IUserBO)userInfo;

userBO.setPassword("abc");

 

//我要执行动作了,我就认为是一个业务逻辑类

IUserBiz userBiz = (IUserBiz)userInfo;

userBiz.deleteUser();

}

}







从新拆分成两个接口,IUserBO负责用户属性,收集和反馈用户的属性信息,IUserBiz负责用户行为,完成用户信息的维护和变更。

       电话通话的时候有4个过程发生:拨号,通话,回应,挂机。其类图如下:

<<电话类图.vsdx>>


public interface IPhone {

 

// 拨通电话

public void dial(String phoneNumber);

 

// 通话

public void chat(Object o);

 

// 通话完毕,挂电话

public void hangup();

}




单一责任原则要求一个借口或者类只有一个原因引起变化,也就是一个接口或类只能一个职责,它就负责一件事情。

IPhone这个接口可不是只有一个职责,它包含两个职责:一个是协议管理,一个是数据传输。Dial()hangup()两个方法实现是协议管理,分别负责拨号接通和挂机,chat()实现的是数据的传输。协议接通的变化会引起这个接口或者实现类的变化,数据传送也会引起这样的变化,但是协议管理和数据传输这两个职责不相互影响。那就考虑拆分成两个接口。

<<职责分明的电话类图.vsdx>>

这样是存在缺陷的,一个手机类要把ConnextionManagerDataTransfer组合在一起才能使用。组合是一种强耦合关系。这样的耦合还不如使用接口实现的方式。

<<简洁清晰职责分明的电话类图.vsdx>>


/**

 *

 * @author liang

 * 协议管理类接口

 */

public interface IConnectionManager {

 

// 拨打电话

void dial(String phoneNumber);

 

// 挂断电话

void hangup();

}


/**

 *

 * @author liang

 *数据传输类接口

 */

public interface IDataTransfer {

 

//输出传输

void DataTransfer(IConnectionManager cm);

}

/**

 *

 * @author liang

 *实现类

 */

public class Phone implements IDataTransfer, IConnectionManager {

 

@Override

public void DataTransfer(IConnectionManager cm) {

System.out.println("正在通话");

}

 

@Override

public void dial(String phoneNumber) {

System.out.println("拨打电话");

}

 

@Override

public void hangup() {

System.out.println("挂断电话");

}

 

}

/**

 *

 * @author liang

 *测试类

 */

public class Client {

 

public static void main(String[] args) {

 

Phone phone = new Phone();

phone.dial("127XXXXXXXX");

phone.DataTransfer(phone);

phone.hangup();

}

}






这样的设计才是比较合理的,一个类实现了两个接口,把两个职责融合在一个类中。这个Phone由两个原因引起变化。如果真要实现类的单一职责,这个就必须使用上面的职责分明的电话类图的模式了,这样会引起类间耦合过重,类的数量增加等问题。

注意:单一职责原则提出了一个编写程序的标准,用"职责""变化原因"来衡量接口或类设计的是否优良。但是这两者都是不可度量的,因项目环境而已。

对于单一职责原则,建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

下面是电话职责的另外一种实现

/**

 *

 * @author liang

 * 协议管理类接口

 */

public interface IConnectionManager {

 

// 拨打电话

void dial(String phoneNumber);

 

// 挂断电话

void hangup();

}

/**

 *

 * @author liang

 *数据传输类接口

 */

public interface IDataTransfer {

 

//输出传输

void DataTransfer(IConnectionManager cm);

}

/**

 *

 * @author liang

 *实现类

 */

public class Phone implements IDataTransfer {

 

@Override

public void DataTransfer(IConnectionManager cm) {

cm.dial("127XXXXXXXX");

System.out.println("正在通话");

cm.hangup();

}

 

}

public class Client {

 

public static void main(String[] args) {

Phone phone = new Phone();

IConnectionManager cm = new IConnectionManager() {

 

@Override

public void hangup() {

System.out.println("开始拨打电话");

}

 

@Override

public void dial(String phoneNumber) {

System.out.println("挂断电话");

}

};

phone.DataTransfer(cm);

}

}





 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值