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

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

问题描述

我正在尝试学习SOLID设计,并认为自己犯了一个错误。我认为 Player 类中的 IItem 接口未遵循 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.

在您的示例中,这可能意味着定义 MagicalWholeBodyArmor 不能容纳在 Slot 中,因此如果尝试访问其 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 Principle 。打开/关闭原则的一个好的经验法则是:如果我更改了这部分代码,那么我还必须在其他地方更改多少其他代码?。如果答案是很多,那可能是因为您违反了开放/封闭原则。

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天全站免登陆