我正在学习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());
}
}
我在SOLID中创建了另一个用于显示信息的类,如“ S”规则所述,该类不应执行不应做的事情。而且我认为显示信息不是任务。 (如果我错了,请纠正我)
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 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类?有可能还是我对SOLID原则的理解是错误的。如果您发现我做错了或不好的做法,请纠正我:)
最佳答案
从理论上讲,您提出的问题的实现看起来不错;但是,在现实世界中确实存在一些设计问题。
尽管“单一职责原则”确实促进了更多的凝聚力类,但不应将其扩展到将所有功能都移到新类的水平。最好的例子是DisplayPerson
类,它根本不是必需的(或者应该以不同的方式实现,我将在稍后讨论)。类代表现实世界的对象。在现实世界中,如果您问一个人的名字,他们会告诉您他们的名字,而不是将您重定向到另一个告诉您他们的名字的人。因此,允许Person
对象具有一种打印其自身属性的方法,并且这丝毫不违反单一职责原则。武器也是如此。
如果武器支持此功能/行为,请考虑您要打印武器的range
。就目前而言,DisplayPerson
具有-IWeapon
引用,但IWeapon
并不包含ranges
作为合同的一部分。然后如何打印武器的range
? (将无法通过range
方法中的iwep
引用访问DisplayAll
)。您将必须使用typeOf
检查,然后将IWeapon
下放到IWeaponV1
,以便可以调用ranges
方法。这种方法的问题在于,DisplayPerson
现在必须使用两个不同的接口,而不是使用单个接口。 (更不用说有条件检查违背了使用通用接口的目的)
牢记以上几点,您可以进行以下代码更改:
将display
方法添加到IWeapon
界面和Person
类。
在display
类的Person
方法中打印人员的属性。同样,在单个武器实现的display
方法中打印武器的属性
通过上述更改,您可以依靠单个界面(而不会违反单一职责原则)直接在Person
类中的IWeapon
或DisplayPerson
对象上调用display:
public void DisplayAll() {
Console.WriteLine("Person " + pers.display() + "\n has weapon: " + iwep.display());
}