下面以两个例子来解释一下单一原则(工程源代码)
【案例1】用户权限系统
设计案例用户权限系统(用户、机构、角色管理这些模块),基本上使用的都是RBAC模型(基于角色的访问控制,通过分配和取消角色来完成用户权限的授予和取消,使动作主体(用户)与资源的行为(权限)分离),确实是一个很好的解决方案。
传统方法:
#include <QCoreApplication>
#include <iostream>
/*!
* \brief The UserInfo class
*/
class UserInfo
{
public:
void SetUserID(std::string userID);
std::string GetUserID();
void SetUserName(std::string userName);
std::string GetUserName();
void SetUserPasswd(std::string userPasswd);
std::string GetUserPasswd();
void DeleteUser(std::string userName);
void ChangeUserPasswd(std::string &oldUserPasswd,std::string &newUserPasswd);
void AddOrg(int orgID);
void AddRole(int roleID);
private:
std::string _user_id;
std::string _user_name;
std::string _user_passwd;
};
/*!
* \brief UserInfo::SetUserID
* \param userID
*/
void UserInfo::SetUserID(std::string userID)
{
this->_user_id = userID;
}
/*!
* \brief UserInfo::GetUserID
* \return
*/
std::string UserInfo::GetUserID()
{
std::cout<<this->_user_id.c_str()<<std::endl;
return this->_user_id;
}
/*!
* \brief UserInfo::SetUserName
* \param userName
*/
void UserInfo::SetUserName(std::string userName)
{
this->_user_name = userName;
}
/*!
* \brief UserInfo::GetUserName
* \return
*/
std::string UserInfo::GetUserName()
{
std::cout<<this->_user_name.c_str()<<std::endl;
return this->_user_name;
}
/*!
* \brief UserInfo::SetUserPasswd
* \param userPasswd
*/
void UserInfo::SetUserPasswd(std::string userPasswd)
{
this->_user_passwd = userPasswd;
}
/*!
* \brief UserInfo::GetUserPasswd
* \return
*/
std::string UserInfo::GetUserPasswd()
{
std::cout<<this->_user_passwd.c_str()<<std::endl;
return this->_user_passwd;
}
/*!
* \brief UserInfo::DeleteUser
* \param userName
*/
void UserInfo::DeleteUser(std::string userName)
{
}
/*!
* \brief UserInfo::ChangeUserPasswd
* \param oldUserPasswd
* \param newUserPasswd
*/
void UserInfo::ChangeUserPasswd(std::string &oldUserPasswd, std::string &newUserPasswd)
{
}
/*!
* \brief UserInfo::AddOrg
* \param orgID
*/
void UserInfo::AddOrg(int orgID)
{
}
/*!
* \brief UserInfo::AddRole
* \param roleID
*/
void UserInfo::AddRole(int roleID)
{
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
UserInfo *myUserInfo = new UserInfo;
myUserInfo->SetUserName("lili");
myUserInfo->SetUserID("C-1");
myUserInfo->SetUserPasswd("123456");
myUserInfo->GetUserName();
myUserInfo->GetUserID();
myUserInfo->GetUserPasswd();
delete myUserInfo;
return a.exec();
}
以上设计不符合单一原则,解决方法如下:
依据定义咱们可以再重新设计下,把用户的信息抽取成一个业务对象(Business Object ,BO),把行为抽取成一个业务逻辑(Business Logic,Biz)
#include <QCoreApplication>
#include <iostream>
/*!
* \brief The UserBo class
*/
class UserBo
{
public:
void SetUserID(std::string userID);
std::string GetUserID();
void SetUserName(std::string userName);
std::string GetUserName();
void SetUserPasswd(std::string userPasswd);
std::string GetUserPasswd();
public:
std::string _user_id;
std::string _user_name;
std::string _user_passwd;
};
/*!
* \brief UserBo::SetUserID
* \param userID
*/
void UserBo::SetUserID(std::string userID)
{
this->_user_id = userID;
}
/*!
* \brief UserBo::GetUserID
* \return
*/
std::string UserBo::GetUserID()
{
std::cout<<this->_user_id.c_str()<<std::endl;
return this->_user_id;
}
/*!
* \brief UserBo::SetUserName
* \param userName
*/
void UserBo::SetUserName(std::string userName)
{
this->_user_name = userName;
}
/*!
* \brief UserBo::GetUserName
* \return
*/
std::string UserBo::GetUserName()
{
std::cout<<this->_user_name.c_str()<<std::endl;
return this->_user_name;
}
/*!
* \brief UserBo::SetUserPasswd
* \param userPasswd
*/
void UserBo::SetUserPasswd(std::string userPasswd)
{
this->_user_passwd = userPasswd;
}
/*!
* \brief UserBo::GetUserPasswd
* \return
*/
std::string UserBo::GetUserPasswd()
{
std::cout<<this->_user_passwd.c_str()<<std::endl;
return this->_user_passwd;
}
/*!
* \brief The UserBiz class
*/
class UserBiz
{
public:
void DeleteUser(UserBo myUserBo);
void ChangeUserPasswd(UserBo *myUserBo,std::string &oldUserPasswd,std::string &newUserPasswd);
void AddOrg(UserBo myUserBo,int orgID);
void AddRole(UserBo myUserBo,int roleID);
};
/*!
* \brief UserBiz::DeleteUser
* \param myUserBo
*/
void UserBiz::DeleteUser(UserBo myUserBo)
{
}
/*!
* \brief UserBiz::ChangeUserPasswd
* \param oldUserPasswd
* \param newUserPasswd
*/
void UserBiz::ChangeUserPasswd(UserBo *myUserBo,std::string &oldUserPasswd, std::string &newUserPasswd)
{
if (!myUserBo->_user_passwd.compare(oldUserPasswd)){
myUserBo->_user_passwd = newUserPasswd;
std::cout<<myUserBo->_user_passwd<<std::endl;
}
}
/*!
* \brief UserBiz::AddOrg
* \param myUserBo
* \param orgID
*/
void UserBiz::AddOrg(UserBo myUserBo, int orgID)
{
}
/*!
* \brief UserBiz::AddRole
* \param myUserBo
* \param roleID
*/
void UserBiz::AddRole(UserBo myUserBo, int roleID)
{
}
/*!
* \brief The NewUserInfo class
*/
class UserInfo : public UserBo,public UserBiz
{
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
UserInfo *myUserInfo = new UserInfo;
UserBo *myUserBo= (UserBo *)myUserInfo;
myUserBo->SetUserName("lili");
myUserBo->SetUserID("C-1");
myUserBo->SetUserPasswd("123456");
myUserBo->GetUserID();
myUserBo->GetUserName();
myUserBo->GetUserPasswd();
UserBiz *myUserBiz = (UserBiz *)myUserInfo;
myUserBiz->ChangeUserPasswd(myUserBo,myUserBo->_user_passwd,std::string("789012"));
return a.exec();
}
单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。
在实际应用中,类的设计尽量做到只有一个原因引起变化,接口一定要做到单一职责原则,方法一定要做到单一职责原则,即一个方法只实现一个功能。
参考文献: