我需要更改什么才能正确实施 SOLID 设计? [英] What do I need to change to implement SOLID design correctly?

查看:22
本文介绍了我需要更改什么才能正确实施 SOLID 设计?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习 SOLID 设计,但我认为我犯了一个错误.我认为 IItem 接口在我的 Player 类中不遵循 Liskov 替换原则,但是,我不知道如何解决这个问题.如果我从 IItem 添加一个新的界面绘图,我将不得不更改 Player 的方法以添加一个案例来处理它.

I'm trying to learn SOLID design and think I have made a mistake. I think that the IItem interface does not follow Liskov substitution principle within my Player class however, I can't work out how to fix this. If I add a new interface drawing from IItem I would have to change Player's method to add a case to handle it.

我希望 Player 类只需要一种装备方法,因此需要帮助了解我做错了什么以及如何正确做.

I would like for the Player class to only need one method for equip so need help understanding what I have done wrong and how to do it correctly.

我的界面的简化版:

    interface IItem
    {
        string Name { get; set; }
        int Value { get; set; }
        Quality Quality { get; set; }
        EquipmentType Type { get; set; }
    }
    interface IWeapon : IItem
    {

    }
    interface IArmour : IItem
    {
        int Defence { get; set; }
        Slot Slot { get; set; }
    }

消费玩家类:

    class Player
    {
        private Dictionary<Slot, IArmour> armour = new Dictionary<Slot, IArmour>();
        private IWeapon weapon;

        public bool Equip(IItem item)
        {
            switch (item.Type)
            {
                case EquipmentType.Armour:
                    var armour = item as IArmour;
                    if (this.armour.ContainsKey(armour.Slot))
                    {
                        return false;
                    }
                    this.armour.Add(armour.Slot, armour);
                    return true;
                case EquipmentType.Weapon:
                    var weapon = item as IWeapon;
                    throw new NotImplementedException();
                default:
                    return false;
            }
        }
    }

上下文的枚举:

    enum Slot
    {
        Head = 0,
        Soulders = 1,
        Gloves = 2,
        Neck = 3,
        RRing = 4,
        LRing = 5,
        Torso = 6,
        Legs = 7,
        Boots = 8,
        Bracers = 9,
        Belt = 10,
    }
    enum EquipmentType
    {
        Armour = 0,
        Weapon = 1
    }

推荐答案

Liskov 替换原则 通常是关于您如何定义类的.如果您编写一个派生自其他类(或实现某个接口)的类,那么想法是有人应该能够使用您的类,就好像它是该父类的实例一样.您的子类可能具有父类没有的其他行为(当然,使用您的类的人就好像它是父类的实例一样将无法访问它),但是所有这些行为父类应该在子类中保持完整.

The Liskov Substitution Principle is typically about how you define your classes. If you write a class which derives from some other class (or implements some interface), the idea is that someone should be able to use your class as if it was an instance of that parent class. Your subclass may have additional behaviour which the parent class doesn't have (and someone who's using your class as if it was an instance of the parent class won't be able to access this, of course), but all of the behaviour that the parent class has should stay intact in the child class.

在您的示例中,这可能意味着定义不适合 SlotMagicalWholeBodyArmor,因此如果您尝试访问其 Slot,则会引发异常 属性.将 MagicalWholeBodyArmor 视为 IArmor 的人会在他们试图查看它适合哪个插槽时感到惊讶.

In your example, that might mean defining MagicalWholeBodyArmor which doesn't fit into a Slot, and so throws an exception if you try and access its Slot property. Someone who's treating the MagicalWholeBodyArmor as if it was an IArmor would be in for a surprise when they tried to see what slot it fits into.

您编写的 SOLID 规则确实有点违反了开放/封闭原则.Open/Closed 原则的一个很好的经验法则是如果我更改了这一位代码,我还必须更改其他地方的多少其他代码位?".如果答案是很多",那可能是因为您违反了开放/封闭原则.

The SOLID rule that you code does violate a little bit is the Open/Closed principle. A good rule of thumb for the Open/Closed principle is "If I change this bit of code, how many other bits of code in other places do I also have to change?". If the answer is "lots", then that's probably because you're violating the Open/Closed principle.

在您的情况下,添加新的 EquipmentType 枚举成员意味着您必须在 Player 类中找到该 switch 语句并添加一个新案例.

In your case, adding a new EquipmentType enum member means that you'll have to go and find that switch statement in your Player class and add a new case.

如果只有一个 switch 语句,那还不错.如果您添加一种新类型的设备,那么您的 Player 类可能需要升级无论如何,因此将 switch 语句修改为其中的一部分就可以了.试图以自己的方式解决这个问题意味着需要大量的抽象,但收益却很少.

If there's just the one switch statement, then that isn't too bad. If you add a new type of equipment then your Player class probably needs an upgrade anyway, so modifying the switch statement as part of that is fine. Trying to architect your way around this would mean a significant amount of abstraction for very little gain.

然而,如果你在很多不同的地方有很多 switch 语句,它们都查看 EquipmentType,(并根据它做出不同的决定),你需要找到它们全部并修复它们,那么这更严重地违反了开放/封闭原则,这可能表明您需要重新构建事物以将所有这些独立的、不同的逻辑位集中到一个地方.

However, if you have lots and lots of switch statements in lots of different places which all look at EquipmentType, (and make different decisions based on it), and you'd need to find them all and fix them all, then that's a bigger violation of the Open/Closed principle, and it's probably an indication that you need to re-architect things to bring all of those separate, disparate bits of logic into a single place.

这篇关于我需要更改什么才能正确实施 SOLID 设计?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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