单一责任原则(C#)

 

翻译、参考:https://www.dotnetcurry.com/software-gardening/1148/solid-single-responsibility-principle

 


 

在用面向对象编程很多年后,我发现很多程序员总是违反这个原则。

是的,我们写类和方法,企图以面向过程的方式将逻辑写到同一个方法内,而不是把它们拆分成很多单一的类,每个只负责做一件事。

这里有一些典型的示例代码

public class CsvFileProcessor
{
    public void Process(string filename)
    {
        TextReader tr = new StreamReader(filename);
        tr.ReadToEnd();
        tr.Close();

        var conn = new SqlConnection("server=(local);integrated security=sspi;database=SRP");
        conn.Open();

        string[] lines = tr.ToString().Split(new string[] {@"\r\l"}, StringSplitOptions.RemoveEmptyEntries);
        foreach( string line in lines)
        {
            string[] columns = line.Split(new string[] {","}, StringSplitOptions.RemoveEmptyEntries);
            var command = conn.CreateCommand();
            command.CommandText = "INSERT INTO People (FirstName, LastName, Email) VALUES (@FirstName, @LastName, @Email)";
            command.Parameters.AddWithValue("@FirstName", columns[0]);
            command.Parameters.AddWithValue("@LastName", columns[1]);
            command.Parameters.AddWithValue("@Email", columns[2]);
            command.ExecuteNonQuery();
        }
        conn.Close();
    }
}

 这个类做了几件事?一件?两件?三件?或者更多?

我们用 ParseCsv() 这个方法 CSV文件转换为一行一行的 ,但是StoreCsvData()  这个方法是将行转换为一列一列的。

解决这个问题的方法是 采用ContactDTO  来储存每一行的数据。

下一步是添加DTO,但我将跳过一个步骤,并将每个方法分解到它自己的类中。

但是我同时也预想到一些问题,如果这些数据不是来自CSV呢?如果它来自XML、JSON或者其它数据格式怎么办?

你用 接口 解决了这个问题

public interface IContactDataProvider
{
    string Read();
}
public interface IContactParser
{
    IList<ContactDTO> Parse(string contactList);
}
public interface IContactWriter
{
    void Write(IList<ContactDTO> contactData);
}
public class ContactProcessor
{
    public void Process(IContactDataProvider cdp, IContactParser cp, IContactWriter cw)
    {
        var providedData = cdp.Read();
        var parsedData = cp.Parse(providedData);
        cw.Write(parsedData);
    }
}
public class CSVContactDataProvider : IContactDataProvider
{
    private readonly string _filename;

    public CSVContactDataProvider(string filename)
    {
        _filename = filename;
    }
    
    public string Read()
    {
        TextReader tr = new StreamReader(_filename);
        tr.ReadToEnd();
        tr.Close();
        return tr.ToString();
    }
}

public class CSVContactParser : IContactParser
{
    public IList<ContactDTO> Parse(string csvData)
    {
        IList<ContactDTO> contacts = new List<ContactDTO>();
        string[] lines = csvData.Split(new string[] { @"\r\l" }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string line in lines)
        {
            string[] columns = line.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            var contact = new ContactDTO
            {
                FirstName = columns[0],
                LastName = columns[1],
                Email = columns[2]
            };
            contacts.Add(contact);
        }

        return contacts;
    }
}

public class ADOContactWriter : IContactWriter
{
    public void Write(IList<ContactDTO> contacts)
    {
        var conn = new SqlConnection("server=(local);integrated security=sspi;database=SRP");
        conn.Open();
        foreach (var contact in contacts)
        {
            var command = conn.CreateCommand();
            command.CommandText = "INSERT INTO People (FirstName, LastName, Email) VALUES (@FirstName, @LastName, @Email)";
            command.Parameters.AddWithValue("@FirstName", contact.FirstName);
            command.Parameters.AddWithValue("@LastName", contact.LastName);
            command.Parameters.AddWithValue("@Email", contact.Email);
            command.ExecuteNonQuery();
        }
        conn.Close();

    }
}

public class ContactDTO
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

 

单一责任原则(C#)

上一篇:如何Windows分页控件中增加统计功能


下一篇:C# 委托 、事件、同步、异步知识点归纳