我很难理解是否有时可以接受违反单一责任原则,或者是否应该不惜一切代价避免这种原则。
请注意,以下代码已简化为仅保留相关部分。
我有Hero
类,代表一个角色,它可以拥有不同的Items
倍数。
我有从Items
继承的倍数类,例如QuestItems
和BackpackItems
。
当我想在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,但我现在不太明白为什么会这么糟糕。
我更喜欢使用哪种实施方案? (另一个?)
答案 0 :(得分:2)
那么,只有Heros“拥有”存储库中的项目?是否有位置,非英雄人物(也许是怪物)等谁也可以拥有物品?
由于您提到这是简化的,因此很难对正确的方法给出明确的答案。也许两者都不是。
对我而言,这类问题并不是关于SRP,而是关于通用内容应该是什么,以及与KISS的平衡。例如,可能是一个更好的解决方案,可以完全解开项目和英雄,而是有交互规则,决定哪个对象可以用于哪个英雄或角色。因为你可能遇到的下一个问题是你有不同类型的英雄,也许是巫师和战士,他们不能用相同的物品做同样的事情。
另外,请记住,OOP(单一)继承通常不能很好地映射到现实世界的情况;考虑使用更多的组合模型。
答案 1 :(得分:1)
首先,SRP很容易被提及和引用,但实际上通常会非常强烈地 。只是计算"什么是一个要求" (应该进入一个班级)可能很难。
在你的情况下,一个替代方案可能是将一个项目添加到某个Hero(或Monster或Whatever!)到自己的类中的责任。含义:有时创建一个服务类来实现影响其他类A,B,C ......的特定行为是有意义的,但这实际上并不适用于任何类A,B,C,......
你知道,并非所有课程都需要反映"对象"。他们也可以代表"行为"!因此,请考虑一些 ItemAdderService 是否会对您有所帮助!