SRP - 单一责任原则

SOLID 中的 S 代表单一责任原则(SRP)。

** 在这种情况下,责任意味着改变的原因,因此该原则规定一个类应该只有一个改变的理由。

Robert C. Martin 在 2014 年 9 月 10 日的耶鲁管理学院讲座中表示如下

你还可以说,不要将因不同原因而更改的函数放在同一个类中。

要么

不要在课堂上混淆顾虑

申请 SRP 的原因:

更改类时,可能会影响与该类其他职责相关的功能。将责任保持在较低水平可以最大限度地降低副作用的风险。

不好的例子

我们有一个接口 IWallet 和一个实现 IWallet 的 Wallet 类。钱包持有我们的钱和品牌,此外它应该打印我们的钱作为字符串表示。该类由…使用

  1. 一个网络服务
  2. 一个文本作者,用欧元将钱打印成文本文件。

StackOverflow 文档

SRP 在这里受到了侵犯,因为我们有两个问题:

  1. 存钱和品牌
  2. 钱的代表。

C#示例代码

public interface IWallet
{
    void setBrand(string brand);
    string getBrand();
    void setMoney(decimal money);
    decimal getMoney();
    string printMoney();
}

public class Wallet : IWallet
{
    private decimal m_Money;
    private string m_Brand;

    public string getBrand()
    {
        return m_Brand;
    }

    public decimal getMoney()
    {
        return m_Money;
    }

    public void setBrand(string brand)
    {
        m_Brand = brand;
    }

    public void setMoney(decimal money)
    {
        m_Money = money;
    }

    public string printMoney()
    {
        return m_Money.ToString();
    }
}

好例子

StackOverflow 文档

为了避免违反 SRP,我们从钱包类中删除了 printMoney 方法并将其放入 Printer 类中。Printer 类现在负责打印,Wallet 现在负责存储值。

C#示例代码

public interface IPrinter
{
    void printMoney(decimal money);
}

public class EuroPrinter : IPrinter
{
    public void printMoney(decimal money)
    {
        //print euro
    }
}

public class DollarPrinter : IPrinter
{
    public void printMoney(decimal money)
    {
        //print Dollar
    }
}

public interface IWallet
{
    void setBrand(string brand);
    string getBrand();
    void setMoney(decimal money);
    decimal getMoney();
}

public class Wallet : IWallet
{
    private decimal m_Money;
    private string m_Brand;

    public string getBrand()
    {
        return m_Brand;
    }

    public decimal getMoney()
    {
        return m_Money;
    }

    public void setBrand(string brand)
    {
        m_Brand = brand;
    }

    public void setMoney(decimal money)
    {
        m_Money = money;
    }
}