我正在学习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类中的IWeaponDisplayPerson对象上调用display:

public void DisplayAll() {
        Console.WriteLine("Person " + pers.display() + "\n has weapon: " + iwep.display());
}

09-06 12:57