C# 具有两个不同接口的构造函数注入(单一责任和接口隔离)
我正在学习坚实的原则。我现在正在使用依赖注入和接口隔离原则。我已经掌握了这两个方面的基本知识,但当我把它们结合起来时,我感到困惑。这是我的实现C# 具有两个不同接口的构造函数注入(单一责任和接口隔离),c#,design-patterns,dependency-injection,solid-principles,single-responsibility-principle,C#,Design Patterns,Dependency Injection,Solid Principles,Single Responsibility Principle,我正在学习坚实的原则。我现在正在使用依赖注入和接口隔离原则。我已经掌握了这两个方面的基本知识,但当我把它们结合起来时,我感到困惑。这是我的实现 class Person { public Person(string name, int age) { Name = name; Age = age; } public string Name { get; set; } public int Age { get; set; }
class Person
{
public Person(string name, int age)
{
Name = name;
Age = age;
}
public string Name { get; set; }
public int Age { get; set; }
}
class DisplayPerson
{
private readonly IWeapon iwep;
private readonly Person pers;
public DisplayPerson(IWeapon iwep, Person perss)
{
this.iwep = iwep;
this.pers = perss;
}
public void DisplayAll()
{
Console.WriteLine("Name: " + pers.Name + "\nAge: " + pers.Age + "\n" + "Weapon: "
+ iwep.weaponName() + "\nDamage: " + iwep.damage().ToString());
}
}
我创建了另一个类,用于将信息显示为SOLID中的“S”规则,即一个类不应该做它不应该做的事情。我认为显示这些信息不是它的任务。(如果我错了,请纠正我)
有了这个界面,我现在可以添加很多有武器名称和伤害的武器。但是,如果我想增加另一种具有附加功能的武器,我们必须遵循ISP原则,对吗?所以我在下面创建了这个接口和类
class Gun : IWeaponV1
{
private string weaponNames;
private int damages;
private int range;
public Gun(string weaponName, int damage, int range)
{
this.weaponNames = weaponName;
this.damages = damage;
this.range = range;
}
public string weaponName() { return this.weaponNames; }
public int damage(){ return this.damages; }
public int ranges() { return this.range; }
}
public interface IWeaponv1 : IWeapon
{
int range();
}
我是这样实现的
static void Main(string[] args)
{
DisplayPerson disp = new DisplayPerson(new Sword("Samurai Sword", 100), new Person("Jheremy", 19));
disp.DisplayAll();
Console.ReadKey();
}
我的问题是如何将IWeaponv1注入上面的DisplayPerson类?有可能吗?或者我对坚实原则的理解是错误的。如果你看到我做了错事或不好的练习,请纠正我:)有时会与你可以遵循的单一责任原则相混淆,所以没关系 在回答您的问题之前,我想指出代码中的几个问题
DisplayPerson disp = new DisplayPerson(new Sword("Samurai Sword", 100), new Person("Jheremy", 19));
DisplayPerson disp1 = new DisplayPerson(new Gun("Shotgun Axe", 100,100), new Person("Matt", 22);
//Assuming you have implemented Gun:IWeaponv1
这看起来不错,它没有违反单一责任原则。在这个简单的例子中,你想得太多了。在上面的示例中,只有一个具有功能的类(displayperson)存在,其余的只是保存数据。当您将数据与功能分离时,这是一件好事。检查单个责任是否被破坏的一种简单方法是,对照类的名称检查方法名称。如果它不合适,那么您违反了SRP 从理论角度来看,您在问题中提出的实施方案看起来不错;然而,它在现实世界中确实存在一些设计问题
DisplayPerson
类根本不是必需的(或者应该以不同的方式实现,我将在稍后讨论)。类表示真实世界的对象。在现实世界中,如果你问一个人的名字,他们会告诉你他们的名字,而不是把你引向另一个告诉你他们名字的人。因此,允许Person
对象具有打印其自身属性的方法,并且这不会以任何方式违反单一责任原则。武器也是如此范围。目前,DisplayPerson
有一个IWeapon
参考,但IWeapon
没有范围
作为其合同的一部分。那么如何打印武器的射程
?(DisplayAll
方法中的iwep
参考将无法访问range
)。您必须使用typeOf
检查,然后向下转换IWeapon
到IWeaponV1
,以便调用范围
方法。这种方法的问题是,DisplayPerson
现在必须使用两个不同的接口,而不是使用单个接口。(更不用说违背使用公共接口目的的条件检查了)
display
方法添加到IWeapon
界面和Person
类中李>
person
类的display
方法中打印人员的属性。同样,在单个武器实施的显示方法中打印武器的属性
DisplayPerson
类中的Person
或IWeapon
对象上直接调用display:
对于这种结构,最好使用继承而不是接口。例如,
公共抽象类{}
而不是IWeapon
。我认为您代码中的类是新的而不是可注入的。有关更多详细信息,请参阅本文:可能您希望将DisplayPerson
转换为一个名为“PersonDisplayer”的“服务”,该服务将武器和人员(可更新项)作为方法参数,而不是依赖项。看看这篇文章:我非常感谢你的回答。谢谢你也纠正了我的错误:)但我认为你上面的例子“DisplayPerson disp1…”不起作用,因为你正在将“Gun class”注入IWeapon。这是我目前最大的问题。当你这么做的时候,你的问题就会消失。做那有什么问题?天哪!你们是天才。很抱歉,我在StackOverflow中编辑了我的错误,我还以为我在应用程序中也更改了代码。对不起,再说一遍。@CarbineCoder我不同意。该准则违反了单一责任原则,因为它过度使用和误用了该原则。详细解释请参见我的答案。您好@CKing,您是说DisplayPerson类是无用的吗?我应该删除它吗?最后,在这种实现中使用接口是一个坏主意吗?我应该使用简单继承(抽象类),因为它是不可更新的
DisplayPerson disp = new DisplayPerson(new Sword("Samurai Sword", 100), new Person("Jheremy", 19));
DisplayPerson disp1 = new DisplayPerson(new Gun("Shotgun Axe", 100,100), new Person("Matt", 22);
//Assuming you have implemented Gun:IWeaponv1
public void DisplayAll() {
Console.WriteLine("Person " + pers.display() + "\n has weapon: " + iwep.display());
}