独望枫

人在尘世间,有缘自相见,变化千千万,未开窍,已迷恋
posts - 45, comments - 0, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

设计模式之单一职责原则

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;
    };
};

总结

由上面的两次相同的变更需求(都是需要支持一个新的物种),得出来的三种解决方案,其中各自的好坏如下:

方案一:不遵循单一原则
好处:不需要增加其他类
           不需要增加方法
           不需要改动到客户端代码
坏处:增加复杂度
           不方便维护
           更不方便扩展,如果有更多物种,判断将是一长串

 

方案二:方法层面遵循单一原则:每一个不同的方法对应每一种呼吸方式
好处:方便扩展
           无需额外判断
          (主要看复杂度,这里的逻辑足够简单,是该例子最好的修改方案)
坏处:使用时需要用户自行判断使用那种方法
           只是从方法层面遵循违单一原则,不是完全遵循

 

方案三:完全遵循单一原则:每一个类对应每一种呼吸方式
好处:降低类的复杂度,方便维护
           提高类的可读性,可维护性
           降低需求变更引起的其他功能错误的风险,因为需求变更无法预测和避免
坏处:更改一个需求,可能需要增加细分类进行职责界定
           需要牵涉到客户端的代码修改


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理