在尝试模拟我的域时,我遇到了以下问题.让我们看看我们有一件事:
class Thing
{
public int X { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
东西有一个属性X.然后,有Packs,聚合东西.但该域名要求包装可以容纳的东西有一些限制.例如,Xes的累积值不能高于某个特定限制:
class Pack
{
private readonly List<Thing> myThings = new List<Thing>();
private const int MaxValue = 5;
public void Add(Thing thing)
{
if (myThings.Sum(t => t.X) + thing.X > MaxValue)
throw new Exception("this thing doesn't fit here");
myThings.Add(thing);
}
public int Count
{
get { return myThings.Count; }
}
public Thing this[int index]
{
get { return myThings[index]; }
}
}
Run Code Online (Sandbox Code Playgroud)
所以我在为条件添加Thing之前检查,但它仍然很容易陷入麻烦:
var pack = new Pack();
pack.Add(new Thing { X = 2 });
pack.Add(new Thing { X = 1 });
var thingOne = new Thing { X = 1 };
var thingTwo = new Thing { X = 3 };
//pack.Add(thingTwo); // exception
pack.Add(thingOne); // OK
thingOne.X = 5; // trouble
pack[0].X = 10; // more trouble
Run Code Online (Sandbox Code Playgroud)
在C++中,解决方案是在插入时复制并在索引器中返回const引用.如何在C#(可能还有Java)中围绕这个问题进行设计?我似乎无法想到一个好的解决方案:
任何想法或首选解决方案?
编辑:
回到这个问题......我接受了Itay的回复.他是对的.最初的问题是,从一个上下文中你会想要一个Thing对象是不可变的,并且从不同的上下文中,你会希望它是可变的.这需要一个单独的界面......也许吧.我说"也许",因为大部分时间,Pack都是物质的聚合物(在DDD意义上),因此是对象的所有者 - 这意味着它不应该让你能够改变拥有的对象(或者返回一个副本或返回一个不可变的接口).
很高兴在C++中,const修饰符可以很容易地处理这个特殊的东西.如果你想把事情保持在一致的状态,那么看起来好像很少编码.
让Thing一成不变.
class Thing
{
public Thing (int x)
{
X = x;
}
public int X { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
另外,if (myThings.Sum(t => t.X) + thing.X > MaxValue)我认为最好在包中保存一个sum字段,这样你就不必每次重新计算总和.
编辑
对不起 - 我错过了你说你需要它可变的事实.
但是......你的c ++解决方案将如何运作?我不太了解c ++,但c ++常量引用是否会阻止对包装上的实例进行更改?
EDIT2
使用界面
public interface IThing
{
int X { get; }
}
public class Thing : IThing
{
int X { get; set; }
}
class Pack
{
private readonly List<IThing> myThings = new List<IThing>();
private const int MaxValue = 5;
public void Add(IThing thing)
{
if (myThings.Sum(t => t.X) + thing.X > MaxValue)
throw new Exception("this thing doesn't fit here");
myThings.Add(new InnerThing(thing));
}
public int Count
{
get { return myThings.Count; }
}
public IThing this[int index]
{
get { return myThings[index]; }
}
private class InnerThing : IThing
{
public InnerThing(IThing thing)
{
X = thing.X;
}
int X { get; private set; }
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
304 次 |
| 最近记录: |