SRP应该始终受到尊重吗?

时间:2016-09-30 15:33:16

标签: c# single-responsibility-principle

我很难理解是否有时可以接受违反单一责任原则,或者是否应该不惜一切代价避免这种原则。

请注意,以下代码已简化为仅保留相关部分。

我有Hero类,代表一个角色,它可以拥有不同的Items倍数。
我有从Items继承的倍数类,例如QuestItemsBackpackItems
当我想在Item上添加Hero时,根据Item的种类,我应采取不同的行动。
我尝试过两种不同的方式,第一种方式是尊重SRP:

 public abstract class Item
{
    private string _Name{get;set;}

    public string Name
    {
        get
        {
            return _Name;
        }
        protected set
        {
            if (_Name != value)
            {
                _Name = value;
            }
        }
    }
}

public class QuestItem: Item
{
    public QuestItem(String name)
    {
        Name = name;
    }
}

public class BackpackItem: Item
{
    public BackpackItem(String name)
    {
        Name = name;
    }
}
public class Hero
{
   public void AddItem(Item item){
      if(item is QuestItem){
         //Do stuff to add QuestItem
         return;
      }
      if(item is BackpackItem){
         //Do stuff to add BackpackItem
         return;
      }
   }
}

优点:SRP受到尊重 缺点:如果我创建一个继承自Item的新项目类型而忘记在AddItem中更改我的Hero功能,那么我会冒很大的麻烦。

我的第二个解决方案并不尊重SRP:
我的AddItem函数变为

public void AddItem(Item item){
          item.AddToHero(this);
       }

我的Items类变为:

 public abstract class Item
{
    private string _Name{get;set;}

    public string Name
    {
        get
        {
            return _Name;
        }
        protected set
        {
            if (_Name != value)
            {
                _Name = value;
            }
        }
    }
  public abstract void AddToHero(Hero hero);
}

public class QuestItem: Item
{
    public QuestItem(String name)
    {
        Name = name;
    }
    public override void AddToHero(Hero hero)
    {
       //Do my stuff to add my QuestItem to Hero
    }
}

public class BackpackItem: Item
{
    public BackpackItem(String name)
    {
        Name = name;
    }
    public override void AddToHero(Hero hero)
    {
       //Do my stuff to add my BackpackItem to Hero
    }
}

优点:我无法从新的Item类中忘记add方法,因为我在编译时会出错。 缺点:我不尊重SRP,但我现在不太明白为什么会这么糟糕。

我更喜欢使用哪种实施方案? (另一个?)

2 个答案:

答案 0 :(得分:2)

那么,只有Heros“拥有”存储库中的项目?是否有位置,非英雄人物(也许是怪物)等谁也可以拥有物品?

由于您提到这是简化的,因此很难对正确的方法给出明确的答案。也许两者都不是。

对我而言,这类问题并不是关于SRP,而是关于通用内容应该是什么,以及与KISS的平衡。例如,可能是一个更好的解决方案,可以完全解开项目和英雄,而是有交互规则,决定哪个对象可以用于哪个英雄或角色。因为你可能遇到的下一个问题是你有不同类型的英雄,也许是巫师和战士,他们不能用相同的物品做同样的事情。

另外,请记住,OOP(单一)继承通常不能很好地映射到现实世界的情况;考虑使用更多的组合模型。

答案 1 :(得分:1)

首先,SRP很容易被提及和引用,但实际上通常会非常强烈地 。只是计算"什么是一个要求" (应该进入一个班级)可能很难。

在你的情况下,一个替代方案可能是将一个项目添加到某个Hero(或Monster或Whatever!)到自己的类中的责任。含义:有时创建一个服务类来实现影响其他类A,B,C ......的特定行为是有意义的,但这实际上并不适用于任何类A,B,C,......

你知道,并非所有课程都需要反映"对象"。他们也可以代表"行为"!因此,请考虑一些 ItemAdderService 是否会对您有所帮助!