具有两个不同接口的构造函数注入(单一职责和接口隔离)
Constructor injection with two different interfaces (Single Responsibility and Interface Segregation)
我正在学习 SOLID 原则。我现在正在研究依赖注入和接口隔离原则。我已经掌握了这两者的基础知识,但是当我将它们结合起来时,我感到困惑。这是我的实现..
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());
}
}
我创建了另一个 class 用于显示信息,因为 SOLID 中的 "S" 规则说 class 不应该做它不应该做的事情。我认为显示这些信息不是它的任务。 (如有错误请指正)
class Sword : IWeapon
{
private string weaponNames;
private int damages;
public Sword(string weaponName, int damage)
{
this.weaponNames = weaponName;
this.damages = damage;
}
public string weaponName(){ return this.weaponNames; }
public int damage(){ return this.damages; }
}
public interface IWeapon
{
string weaponName();
int damage();
}
有了这个 IWeapon 接口,我现在可以添加许多具有武器名称和伤害的武器。但是如果我想再增加一个武器,增加功能,我们就得遵循ISP原则,对吧?所以我在下面创建了这个界面和class。
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 class?是否可能,或者我对 SOLID 原则的理解是错误的。如果您发现我做错了什么或不好的做法,请纠正我:)
有时会混淆 far you can follow 单一职责原则,所以没关系。
在回答您的问题之前,我想指出一些关于代码的问题。
- WeaponName、Damage 和Range 是数据,不是功能。它们应该声明为 属性 而不是方法。
- Gun 应该实现 IWeaponv1 。我想你误会了。
- 所有属性都在构造函数中设置,即构造函数注入。在这种情况下,Person class 或任何其他 classes
不需要私有集
终于到了你的实际问题
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
这看起来不错,不违反单一职责原则。在这个简单的例子中,你想多了。在上面的示例中,只有一个 class(Display person) 具有功能,其余的只是保存数据。当您将数据与功能分开时,这是一件好事。检查单一职责是否被破坏的一种简单方法是根据 class 的名称检查方法名称。如果它不合适,那么你就违反了 SRP。
从理论上看,您在问题中提出的实施看起来不错;但是,它在现实世界中确实存在一些设计问题。
虽然单一职责原则确实促进了更具凝聚力的 classes,但不应将其扩展到将每个功能都移动到新 class 的级别。典型的例子是根本不需要的 DisplayPerson
class(或者应该以不同的方式实现,我将在稍后讨论)。 类 代表真实世界的对象。在现实世界中,如果你问一个人他们的名字,他们会告诉你他们的名字,而不是将你重定向到另一个告诉你他们的名字的人。因此,一个 Person
对象被允许有一个方法来打印它自己的属性,这不会以任何方式违背单一职责原则。武器也一样。
如果武器支持此 functionality/behavior,请考虑打印武器的 range
。目前,DisplayPerson
has-a IWeapon
参考但 IWeapon
没有 ranges
作为其合同的一部分.那么如何打印武器的 range
呢? (range
将无法通过 DisplayAll
方法中的 iwep
引用访问)。您将必须使用 typeOf
检查,然后将 IWeapon
向下转换为 IWeaponV1
以便您可以调用 ranges
方法。这种方法的问题是 DisplayPerson
现在必须使用两个不同的接口,而不是使用一个接口。 (更不用说违背使用通用接口目的的条件检查)
牢记以上几点,您可以进行以下代码更改:
- 将
display
方法添加到IWeapon
接口和Person
class。
- 在
Person
class的display
方法中打印人物的属性。同样,在单个武器实现的 display
方法中打印武器的属性
通过上述更改,您可以依靠单个界面(不带 违反 单一职责原则) :
public void DisplayAll() {
Console.WriteLine("Person " + pers.display() + "\n has weapon: " + iwep.display());
}
我正在学习 SOLID 原则。我现在正在研究依赖注入和接口隔离原则。我已经掌握了这两者的基础知识,但是当我将它们结合起来时,我感到困惑。这是我的实现..
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());
}
}
我创建了另一个 class 用于显示信息,因为 SOLID 中的 "S" 规则说 class 不应该做它不应该做的事情。我认为显示这些信息不是它的任务。 (如有错误请指正)
class Sword : IWeapon
{
private string weaponNames;
private int damages;
public Sword(string weaponName, int damage)
{
this.weaponNames = weaponName;
this.damages = damage;
}
public string weaponName(){ return this.weaponNames; }
public int damage(){ return this.damages; }
}
public interface IWeapon
{
string weaponName();
int damage();
}
有了这个 IWeapon 接口,我现在可以添加许多具有武器名称和伤害的武器。但是如果我想再增加一个武器,增加功能,我们就得遵循ISP原则,对吧?所以我在下面创建了这个界面和class。
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 class?是否可能,或者我对 SOLID 原则的理解是错误的。如果您发现我做错了什么或不好的做法,请纠正我:)
有时会混淆 far you can follow 单一职责原则,所以没关系。
在回答您的问题之前,我想指出一些关于代码的问题。
- WeaponName、Damage 和Range 是数据,不是功能。它们应该声明为 属性 而不是方法。
- Gun 应该实现 IWeaponv1 。我想你误会了。
- 所有属性都在构造函数中设置,即构造函数注入。在这种情况下,Person class 或任何其他 classes 不需要私有集
终于到了你的实际问题
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
这看起来不错,不违反单一职责原则。在这个简单的例子中,你想多了。在上面的示例中,只有一个 class(Display person) 具有功能,其余的只是保存数据。当您将数据与功能分开时,这是一件好事。检查单一职责是否被破坏的一种简单方法是根据 class 的名称检查方法名称。如果它不合适,那么你就违反了 SRP。
从理论上看,您在问题中提出的实施看起来不错;但是,它在现实世界中确实存在一些设计问题。
虽然单一职责原则确实促进了更具凝聚力的 classes,但不应将其扩展到将每个功能都移动到新 class 的级别。典型的例子是根本不需要的
DisplayPerson
class(或者应该以不同的方式实现,我将在稍后讨论)。 类 代表真实世界的对象。在现实世界中,如果你问一个人他们的名字,他们会告诉你他们的名字,而不是将你重定向到另一个告诉你他们的名字的人。因此,一个Person
对象被允许有一个方法来打印它自己的属性,这不会以任何方式违背单一职责原则。武器也一样。如果武器支持此 functionality/behavior,请考虑打印武器的
range
。目前,DisplayPerson
has-aIWeapon
参考但IWeapon
没有ranges
作为其合同的一部分.那么如何打印武器的range
呢? (range
将无法通过DisplayAll
方法中的iwep
引用访问)。您将必须使用typeOf
检查,然后将IWeapon
向下转换为IWeaponV1
以便您可以调用ranges
方法。这种方法的问题是DisplayPerson
现在必须使用两个不同的接口,而不是使用一个接口。 (更不用说违背使用通用接口目的的条件检查)
牢记以上几点,您可以进行以下代码更改:
- 将
display
方法添加到IWeapon
接口和Person
class。 - 在
Person
class的display
方法中打印人物的属性。同样,在单个武器实现的display
方法中打印武器的属性
通过上述更改,您可以依靠单个界面(不带 违反 单一职责原则) :
public void DisplayAll() {
Console.WriteLine("Person " + pers.display() + "\n has weapon: " + iwep.display());
}