这一点,在单一责任原则的例子吗? [英] It this an example of the Single Responsibility Principle?

查看:108
本文介绍了这一点,在单一责任原则的例子吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我作了如下的代码示例来学习如何使用泛型方法签名。



为了获得 display()方法为客户和员工,我居然开始用的人物抽象类替换我的 IPerson接口



但后来我停了下来,想起播客中,Bob大叔告诉关于在单一职责原则中,你应该有很多的斯科特Hanselman的小班每做一个具体的事情,即一个Customer类不应该有一个打印()保存() CalculateSalary()方式但是,你应该有一个 CustomerPrinter类 CustomerSaver类 CustomerSalaryCalculator类



这似乎编程一种奇怪的方式。然而,摆脱我的界面也觉得不对劲(既然有这么多的IoC容器和DI例子使用它们本身),所以我决定给单一责任原则一试。



所以下面的代码是不同的,比我过去所编(我会作出一个抽象类,带显示器()方法,并摆脱了接口),但基于什么我听说过的去耦和固体原则,编码(接口和PersonDisplayer类)这一新的方式的我觉得这是去的正确方法。



我的喜欢听到的话,别人同样的方式思考在这个问题上还是会感受到这种正面或负面的影响(例如一个笨拙的数。班每做一特别的事情,等)

 使用系统; 

命名空间TestGeneric33
{
类节目
{
静态无效的主要(字串[] args)
{
集装箱货柜=新的Container();
客户的customer1 = container.InstantiateType<客户>(吉姆,史密斯);
员工employee1 = container.InstantiateType<员工>(乔,汤普森);
Console.WriteLine(PersonDisplayer.SimpleDisplay(的customer1));
Console.WriteLine(PersonDisplayer.SimpleDisplay(employee1));
到Console.ReadLine();
}
}

公共类集装箱
{
公共牛逼InstantiateType< T>(串名字,字符串的lastName)其中T:IPerson,新( )
{$ b $(b T)= OBJ新T();
obj.FirstName =名字;
obj.LastName = lastName的;
返回OBJ;
}
}

公共接口IPerson
{
字符串名字{获得;组; }
字符串名字{获得;组; }
}

公共类PersonDisplayer
{
私人IPerson _person;

公共PersonDisplayer(IPerson人)
{
_person =人;
}

公共字符串SimpleDisplay()
{
返回的String.Format({1},{0},_person.FirstName,_person.LastName) ;
}

公共静态字符串SimpleDisplay(IPerson人)
{
PersonDisplayer personDisplayer =新PersonDisplayer(人);
返回personDisplayer.SimpleDisplay();
}
}

公共类客户:IPerson
{
公共字符串名字{获得;组; }
公共字符串名字{获得;组; }
公共字符串公司{搞定;组; }
}

公共类员工:IPerson
{
公共字符串名字{获得;组; }
公共字符串名字{获得;组; }
公众诠释EmployeeNumber {搞定;组; }
}
}


解决方案

我喜欢把单一职责原则的作为的separation 的。在我开始分裂我的班,你有,我尽量想对每个类应该负责。



您类很简单,能够很好的抽象类正如你所提到的实施打印()保存()功能。我会倾向于保持这种设计在你的电流之一。



但是,如果打印和保存都可能以不同的方式来进行,然后一个专用<$ C更复杂的任务$ C>打印机或包裹类将是必要的,因为这责任现在更加复杂。用于制造新的类的复杂性阈是非常主观的,并且将取决于确切的情况,但在结束时,代码仅仅是我们低人类理解的抽象,这样使它使得它的最直观的。



集装箱类是有点误导。实际上它并不'包含'什么。它实际上是实现了工厂方法模式并将从被命名一个工厂中受益。



另外,你的 PersonDisplayer 从不实例化,并可以通过静态方法提供的全部功能,所以为什么不使它成为一个静态类?它的情况并不少见工具类如打印机或储户是静态的。除非你有一个需要具有不同特性的打印机的不同实例,保持不变。


I made the following code example to learn how to use a generics method signature.

In order to get a Display() method for both Customer and Employee, I actually began replacing my IPerson interface with an Person abstract class.

But then I stopped, remembering a podcast in which Uncle Bob was telling Scott Hanselman about the Single Responsibility Principle in which you should have lots of little classes each doing one specific thing, i.e. that a Customer class should not have a Print() and Save() and CalculateSalary() method but that you should have a CustomerPrinter class and a CustomerSaver class and a CustomerSalaryCalculator class.

That seems an odd way to program. However, getting rid of my interface also felt wrong (since so many IoC containers and DI examples use them inherently) so I decided to give the Single Responsibility Principle a try.

So the following code is different than I have programmed in the past (I would have made an abstract class with a Display() method and got rid of the interface) but based on what I have heard about decoupling and the S.O.L.I.D. principles, this new way of coding (the interface and the PersonDisplayer class) I think this is the right way to go.

I would like to hear if others think the same way on this issue or have experienced positive or negative effects of this (e.g. an unwieldy number of classes each doing one particular thing, etc.).

using System;

namespace TestGeneric33
{
    class Program
    {
        static void Main(string[] args)
        {
            Container container = new Container();
            Customer customer1 = container.InstantiateType<Customer>("Jim", "Smith");
            Employee employee1 = container.InstantiateType<Employee>("Joe", "Thompson");
            Console.WriteLine(PersonDisplayer.SimpleDisplay(customer1));
            Console.WriteLine(PersonDisplayer.SimpleDisplay(employee1));
            Console.ReadLine();
        }
    }

    public class Container
    {
        public T InstantiateType<T>(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; }
    }
}

解决方案

I like to think of the Single Responsibility Principle as an implementation of separation of duties. Before I start splitting my classes as you have, I try to think of what each class should be responsible for.

Your classes are quite simple and lend themselves well to an abstract class with an implemented Print() and Save() functions as you mentioned. I would tend to keep that design over your current one.

However, if printing and saving were more complicated tasks which might be performed in different ways then a dedicated Printer or Saver class would be warranted, since that responsibility is now more complex. The 'complexity' threshold for making a new class is very subjective and will depend on the exact situation, but in the end, the code is just an abstraction for us lowly humans to understand, so make it such that it's the most intuitive.

You Container class is a little misleading. It doesn't actually 'contain' anything. It actually implements the Factory Method Pattern and would benefit from being named a factory.

Also, your PersonDisplayer is never instantiated and can provide all of its functionality through static methods, so why not make it a static class? It's not uncommon for utility classes such as Printers or savers to be static. Unless you have a need to have separate instances of a printer with different properties, keep it static.

这篇关于这一点,在单一责任原则的例子吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆