Posted on 2016-07-10 14:08
小菜枫 阅读(510)
评论(0) 编辑 收藏 引用 所属分类:
学习笔记
单一职责原则:Single Responsibility Priciple,简称SRP。
定义:There should never be more than one reason for a class to change,即不能存在多于一个导致类变更的原因。通俗说法:一个类只负责一项职责。
由来:类C负责两项职责,职责R1,职责R2,当职责R1因某需求导致需要更改类C时,原本正常的R2发生异常。
方案:遵循单一职责原则,不同的职责由不同的类负责。类C1负责职责R1,类C2负责职责R2,这样当R1变更时只会更改到类C1,绝不会影响到职责R2的正常运作,反之亦然。
例子:
原始版本:生物(常见动物:牛,羊,猪,狗,猫,鸡,鸭……)均通过空气进行呼吸。
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过空气呼吸"<<endl;
};
};
需求变更一版本:鱼也是生物的一种,但其通过水进行呼吸。
需求变更一版本之解决方案一:
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
if(string("鱼")==biologyname)
{
cout<<biologyname<<"通过水呼吸"<<endl;
}
else
{
cout<<biologyname<<"通过空气呼吸"<<endl;
}
};
};
需求变更一版本之解决方案二:
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过空气呼吸"<<endl;
};
void BreathForFish(string biologyname)
{
cout<<biologyname<<"通过水呼吸"<<endl;
};
};
需求变更一版本之解决方案三:
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过空气呼吸"<<endl;
};
};
class Fish
{
public:
Fish(void){};
~Fish(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过水呼吸"<<endl;
};
};
需求变更二版本:病毒也是生物的一种,但其通过寄生于其他生物体内存活,假定其通过血液进行呼吸。
需求变更二版本之解决方案一:
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
if(string("鱼")==biologyname)
{
cout<<biologyname<<"通过水呼吸"<<endl;
}
else if (string("病毒")==biologyname||string("沙士")==biologyname||string("非典")==biologyname)//病毒可能会有很多?
{
cout<<biologyname<<"通过血呼吸"<<endl;
}
else
{
cout<<biologyname<<"通过空气呼吸"<<endl;
}
};
};
需求变更二版本之解决方案二:
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过空气呼吸"<<endl;
};
void BreathForFish(string biologyname)
{
cout<<biologyname<<"通过水呼吸"<<endl;
};
void BreathForVirus(string biologyname)
{
cout<<biologyname<<"通过血呼吸"<<endl;
}
};
需求变更二版本之解决方案三:
class Biology
{
public:
Biology(void){};
~Biology(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过空气呼吸"<<endl;
};
};
class Fish
{
public:
Fish(void){};
~Fish(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过水呼吸"<<endl;
};
};
class Virus
{
public:
Virus(void){};
~Virus(void){};
void Breath(string biologyname)
{
cout<<biologyname<<"通过血呼吸"<<endl;
};
};
总结:
由上面的两次相同的变更需求(都是需要支持一个新的物种),得出来的三种解决方案,其中各自的好坏如下:
方案一:不遵循单一原则
好处:不需要增加其他类
不需要增加方法
不需要改动到客户端代码
坏处:增加复杂度
不方便维护
更不方便扩展,如果有更多物种,判断将是一长串
方案二:方法层面遵循单一原则:每一个不同的方法对应每一种呼吸方式
好处:方便扩展
无需额外判断
(主要看复杂度,这里的逻辑足够简单,是该例子最好的修改方案)
坏处:使用时需要用户自行判断使用那种方法
只是从方法层面遵循违单一原则,不是完全遵循
方案三:完全遵循单一原则:每一个类对应每一种呼吸方式
好处:降低类的复杂度,方便维护
提高类的可读性,可维护性
降低需求变更引起的其他功能错误的风险,因为需求变更无法预测和避免
坏处:更改一个需求,可能需要增加细分类进行职责界定
需要牵涉到客户端的代码修改