单一职责原则
创始人
2024-06-02 18:58:02
0

单一职责原则:

就一个类而言,应该只有一个引起它变化的原因,如果一个类承担的职责过多就等于把这些职责耦合在一起,至少会造成以下两方面的问题:

  • 我们要去修改该类中的一个职责可能会影响到该类的其它职责。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。
  • 当客户端仅需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。

我们在设计一个类时要学会发现职责,并把那些职责相互分离,其实要去判断是否应该分离出一个类来并不难,前面说过,一个类应该只有一个引起它变化的原因,如果你能想到其它的原因也能去改变这个类,那么这个类就具有多于1个的职责,就应该考虑类的职责分离。

在之前的这篇博客中,https://blog.csdn.net/weixin_44049823/article/details/128907849,我们实现的计算器实际上也用到了单一职责原则,这里我们选出其中最经典的3.0版本和5.0版本来学习单一职责原则。

3.0版本计算器代码如下:

#include
using namespace std;
#include//业务逻辑
//异常类用于处理异常情况
class opeException
{
public:void getMessage(){cout << "您的输入有误!" << endl;}
};//运算类用于处理运算
class Operation
{
public:Operation(string& _num1, string& _num2, string& _ope) :num1(_num1), num2(_num2), ope(_ope){}//获取运算结果int getResult(){if (!(isStringNum(num1) && isStringNum(num2) && (ope == "+" || ope == "-" || ope == "*" || ope == "/")))throw opeException();if (ope == "+"){re = stoi(num1) + stoi(num2);}else if (ope == "-"){re = stoi(num1) - stoi(num2);}else if (ope == "*"){re = stoi(num1) * stoi(num2);}else if (ope == "/"){if (stoi(num2) != 0){re = stoi(num1) / stoi(num2);}elsethrow opeException();}return re;}
private:int re;string num1;string num2;string ope;//判断一个字符串是不是数字bool isStringNum(string& s){bool flag = true;for (auto e : s)if (!(isdigit(e))){flag = false;break;}return flag;}
};//界面逻辑
int main()
{try{string _num1 = " ";string _num2 = " ";string _ope = " ";cout << "请输入左操作数:" << endl;cin >> _num1;cout << "请输入右操作数:" << endl;cin >> _num2;cout << "请输入操作符" << endl;cin >> _ope;Operation operation(_num1, _num2, _ope);cout << operation.getResult() << endl;}catch (opeException &ex){ex.getMessage();}return 0;
}

仅仅一个运算类Operation就实现了加减乘除4种功能,很明显在这个类中我至少有4个原因去修改这个类,我修改加法算法的时候可能会影响到其它的运算算法,这个类的耦合太高且严重违反了单一职责原则。

修改后的5.0版本如下:

#include
using namespace std;
#include//业务逻辑//异常类用于处理异常情况
class opeException
{
public:void getMessage(){cout << "您的输入有误!" << endl;}
};//运算类
class Operation
{//判断一个字符串是不是数字bool isStringNum(string& s){bool flag = true;for (auto e : s)if (!(isdigit(e))){flag = false;break;}return flag;}protected:bool isError(string& _strNum1, string& _strNum2, string& _ope){if (!(Operation::isStringNum(_strNum1) && Operation::isStringNum(_strNum2) && (_ope == "+" || _ope == "-" || _ope == "*" || _ope == "/"))){return false;}}
public:virtual int getResult() = 0;
};//加法运算类
class addOperation :public Operation
{
private:string strNum1;string strNum2;string ope;int re;
public:addOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}virtual int getResult() override{if (!isError(strNum1, strNum2, ope))throw opeException();elsere = stoi(strNum1) + stoi(strNum2);return re;}
};//减法运算类
class subOperation :public Operation
{
private:string strNum1;string strNum2;string ope;int re;
public:subOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}virtual int getResult() override{if (!isError(strNum1, strNum2, ope))throw opeException();elsere = stoi(strNum1) - stoi(strNum2);return re;}
};//乘法运算类
class mulOperation :public Operation
{
private:string strNum1;string strNum2;string ope;int re;
public:mulOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}virtual int getResult() override{if (!isError(strNum1, strNum2, ope))throw opeException();elsere = stoi(strNum1) * stoi(strNum2);return re;}
};//除法运算类
class divOperation :public Operation
{
private:string strNum1;string strNum2;string ope;int re;
public:divOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}virtual int getResult() override{if (!isError(strNum1, strNum2, ope))throw opeException();else if (stoi(strNum2) != 0)re = stoi(strNum1) / stoi(strNum2);elsethrow opeException();return re;}
};//运算工厂类
class OpeFactory
{
public:Operation& choose(string &_strNum1,string &_strNum2,string &_ope){if (_ope == "+"){operation = new addOperation(_strNum1, _strNum2, _ope);}else if (_ope == "-")operation = new subOperation(_strNum1, _strNum2, _ope);else if (_ope == "*")operation = new mulOperation(_strNum1, _strNum2, _ope);else if (_ope == "/"){operation = new divOperation(_strNum1, _strNum2, _ope);}elseoperation = nullptr;return *operation;}private:Operation* operation;
};//界面逻辑
int main()
{try{string _strNum1 = " ";string _strNum2 = " ";string _ope = " ";cout << "请输入左操作数:" << endl;cin >> _strNum1;cout << "请输入右操作数:" << endl;cin >> _strNum2;cout << "请输入操作符:" << endl;cin >> _ope;OpeFactory factory;Operation* re = &factory.choose(_strNum1, _strNum2, _ope);if (re != nullptr)cout << (*re).getResult() << endl;elsecout << "您的输入有误!" << endl;}catch (opeException ex){cout << "您的输入有误" << endl;}return 0;
}

在5.0版本的计算器代码中,我们将运算类分成了4种类,分别是加法类、减法类、乘法类、除法类,还创建了一个工厂类专门用于根据不同情况实例化对象,每个类只有一个职责,我们要修改某个功能只需要去修改对应的类即可,极大降低了代码之间的耦合。

单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点:

  • 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
  • 提高类的可读性。复杂性降低,自然其可读性会提高。
  • 提高系统的可维护性。可读性提高,那自然更容易维护了。
  • 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...