这是单一责任原则的一个例子吗?

我做了以下代码示例,以了解如何使用generics方法签名。

为了获得Customer和Employee的Display()方法 ,我实际上开始用Person抽象类替换我的IPerson接口

但后来我停下来,记得一个播客,其中鲍勃叔叔告诉Scott Hanselman关于单一责任原则 ,你应该有很多小class,每个class做一件特定的事情,即一个Customerclass不应该有一个Print()Save ()CalculateSalary()方法,但您应该有CustomerPrinter类CustomerSaver类以及CustomerSalaryCalculator类

这似乎是一种奇怪的编程方式。 然而, 摆脱我的界面也感觉不对 (因为很多IoC容器和DI示例本身使用它们)所以我决定尝试单一责任原则。

所以下面的代码与我过去编程的不同 (我会用Display()方法创建一个抽象类并摆脱界面)但是基于我所听到的关于解耦和SOLID原理的内容, 这个新的编码方式 (接口和PersonDisplayer类) 我认为这是正确的方法

我想听听其他人是否在这个问题上采用相同的方式 ,或者是否经历过这种积极或消极的影响(例如,每个人做一件特别的事情都是笨拙的,等等)。

using System; namespace TestGeneric33 { class Program { static void Main(string[] args) { Container container = new Container(); Customer customer1 = container.InstantiateType("Jim", "Smith"); Employee employee1 = container.InstantiateType("Joe", "Thompson"); Console.WriteLine(PersonDisplayer.SimpleDisplay(customer1)); Console.WriteLine(PersonDisplayer.SimpleDisplay(employee1)); Console.ReadLine(); } } public class Container { public T InstantiateType(string firstName, string lastName) where T : IPerson, new() { T obj = new T(); obj.FirstName = firstName; obj.LastName = lastName; return obj; } } public interface IPerson { string FirstName { get; set; } string LastName { get; set; } } public class PersonDisplayer { private IPerson _person; public PersonDisplayer(IPerson person) { _person = person; } public string SimpleDisplay() { return String.Format("{1}, {0}", _person.FirstName, _person.LastName); } public static string SimpleDisplay(IPerson person) { PersonDisplayer personDisplayer = new PersonDisplayer(person); return personDisplayer.SimpleDisplay(); } } public class Customer : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public string Company { get; set; } } public class Employee : IPerson { public string FirstName { get; set; } public string LastName { get; set; } public int EmployeeNumber { get; set; } } } 

我喜欢将单一责任原则视为职责分离的实施。 在我开始分割我的课程之前,我试着想一下每个class级应该负责什么。

你的类很简单,非常适合于一个带有你所提到的Print()Save()函数的抽象类。 我倾向于将这种设计保留在你当前的设计之上。

但是,如果打印和保存是更复杂的任务,可能以不同的方式执行,那么将保证专用的PrinterSaver类,因为现在这个责任更加复杂。 制作新课程的“复杂性”门槛是非常主观的,并且取决于具体情况,但最后,代码只是我们低级人类理解的抽象,所以要使它成为最直观的。

Container类有点误导。 它实际上并不包含任何东西。 它实际上实现了工厂方法模式 ,并且可以从命名工厂中受益。

此外,您的PersonDisplayer永远不会被实例化,并且可以通过静态方法提供其所有function,那么为什么不将它作为静态类呢? 像Printers或savers这样的实用程序类是静态的并不罕见。 除非您需要具有不同属性的打印机的单独实例,否则请将其保持静态。

我认为你走在正确的轨道上。 虽然我不完全确定Container类。 我通常坚持使用对这些对象使用“new”的简单解决方案,除非你对该接口有一些业务驱动的需求。 (在这个意义上,我不认为“整洁”是一个商业要求)

但是,将“存在”客户责任与“展示客户”分开是很好的。 坚持这一点,它是对SOLID原则的很好解释。

我个人已经完全停止在这种代码中使用任何类型的静态方法,我依靠DI在正确的地点和时间获得所有正确的服务对象。 一旦你开始进一步阐述SOLID原则,你会发现你正在制作更多的课程。 尝试使用这些命名约定以保持一致。

好吧,我以前从未听说过这个“单一责任原则”,但是我认为通过拥有这些CustomerPrinter类和CustomerSaver类所做的事情只是将类转换回结构体,并且取消对象定向一切。

例如,如果需要以不同方式打印,这意味着不同的客户类型在CustomerPrinter类中需要不同的情况。 但正如我所理解的那样,OO组织的一个重点,以及使用inheritance树以及所有这些,是为了消除此CustomerPrinter的需要,以了解如何打印所有内容:客户知道如何打印自己。

在任何情况下,我都不相信严格遵循这些范式。 例如,我不确定接口和抽象类之间的区别是什么。 但是我再次成为C ++程序员而不是C#程序员……

几点说明:

  • 一般而言,SRP一切都很好,显示格式与数据的分离也是如此。
  • 考虑到显示等。我宁愿考虑服务,即PersonDisplayer是单一的,无状态的,并提供字符串显示(IPerson)function。 恕我直言,一个特殊的类包装器只是为了提供显示不提供任何优势。
  • 但是,如果您对wpf使用了数据绑定,则可能有一个DisplayablePerson类,如果Person更改,它将传播PropertyChanged。 您可以将DisplayablePerson对象放入ObservableCollection并将其作为某些列表控件的ItemsSource提供。
  • 你需要什么容器,它只用于实例化和配置实例吗?尝试然后客户customer1 =新客户{FirstName =“Jim”,LastName =“Smith”};

  • 另外,我已经尝试过object.Method (…)调用几次,因为它似乎是最快最简单的解决方案。 然而,经过一段时间后,我总是遇到麻烦,最终得到了object.Method(输入someTypeType,…)

您可以查看IFormattable和IFormatProvider 。

该框架具有支持的格式化类。