class Thing { public int X { get; set; } }
东西有一个属性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]; } } }
所以我在为条件添加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
在C中,解决方案是在插入时复制并在索引器中返回const引用.如何在C#(可能还有Java)中围绕这个问题进行设计?我似乎无法想到一个好的解决方案:
>使事物变得不可变 – 但是如果它需要是可变的呢?
>用事件/观察者观察包装中的东西 – 但这意味着Pack强加了Thing的设计;如果东西有更多属性怎么办?然后,由于需要Pack来观察变化,我最终只会遇到一个事件 – 这对我来说似乎很尴尬.
任何想法或首选解决方案?
编辑:
回到这个问题……我接受了Itay的回复.他是对的.
原始问题是,从一个上下文中,您希望Thing对象是不可变的,并且从不同的上下文中,您会希望它是可变的.这需要一个单独的界面……也许吧.我说“也许”,因为大部分时间,Pack都是物品的聚合物(在DDD意义上),因此是对象的所有者 – 这意味着它不应该让你能够改变拥有的对象(或者返回一个副本或返回一个不可变的接口).
很高兴在C中这个特殊的东西可以通过const修饰符轻松处理.如果你想把事情保持在一致的状态,那么看起来好像很少编码.
解决方法
class Thing { public Thing (int x) { X = x; } public int X { get; private set; } }
另外,而不是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; } } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。