假设我有两个类,例如Food
和Barrel
。Barrel
包含一个食物private Food[] stores
数组,用于跟踪其中存储的食物。Barrel
还包含访问和修改stores
的方法,如public void Insert(Food)
和public void Remove(Food)
。
所以Barrel
可以存储Food
。但我也想让Food
知道它存储在哪里,如果有的话。例如,我想要一种方法Food.Rot()
,它只会在食物没有储存的情况下腐烂。
我目前的解决方案是在Food
中有一个属性public Barrel Container { get; set; }
,它跟踪存储在其中的Barrel
的实例,并让Barrel.Insert(Food toAdd)
将toAdd.Container
设置为自己,Barrel.Remove(Food toRemove)
将toRemove.Container
设置为null
(在这种情况下,Food.Rot()
实际上会腐烂食物(。
然而,任何其他类也可以访问Food.Container
,如果它们向其写入,则原始Barrel
在stores
中仍将具有此Food
实例,但Food.Container
将不再反映此实例。
我可以让set方法确保当Food.Container
更改时,它首先调用Container.Remove(this)
,但我真的不希望除了Barrel
之外的任何东西都能设置Food.Container
。
我也可以让Food
根本不存储它的容器,只需让Rot()
调用一个方法bool IsStored()
来检查每个Barrel.stores
,看看调用它的Food
类的实例是否存储在里面,这样就不会有双向的胡言乱语,但这对优化来说似乎很糟糕。
感觉在这个设计的某个地方,我违反了OOP,我希望理想情况下,整个情况需要重新设计。我也非常乐意接受这样的反馈。
当食物添加到桶中时,您必须修改食品的木桶属性。此外,当设置了桶属性时,如果不存在,则必须将食物添加到水桶中。检查是否存在很重要,因为否则,这两者将相互调用以导致StackOverflow异常。
移除时也必须重复相同的方法。这是您需要的样品:
public class Food
{
public string Name { get; set; }
private Barrel _barrel;
public Barrel Barrel
{
get
{
return _barrel;
}
set
{
if (_barrel != null && _barrel != value)
{
_barrel.Remove(this);
}
if (value != null)
{
value.Insert(this);
}
_barrel = value;
}
}
public override string ToString()
{
return Name+"@"+ Barrel??"";
}
}
public class Barrel
{
public string Name { get; set; }
public List<Food> Stores { get; set; } = new List<Food>();
public void Insert(Food food)
{
if (!Stores.Contains(food))
{
Stores.Add(food);
food.Barrel = this;
}
}
public void Remove(Food food)
{
if (Stores.Contains(food))
{
Stores.Remove(food);
food.Barrel = null;
}
}
public override string ToString()
{
return Name;
}
}
测试代码:
Barrel b0 = new Barrel() { Name = "Barrel 0" };
Barrel b1 = new Barrel() { Name = "Barrel 1" };
//Use insert method.
Food fish = new Food() { Name = "Fish" };
//I will insert fish to b0 first.
b0.Insert(fish);
b1.Insert(fish);
//Assign barrel directly
Food chicken = new Food() { Barrel = b0, Name = "Chicken" };
//then change barrel
chicken.Barrel = b1;
Debug.WriteLine("Barrel 1:"+ string.Join(",",b1.Stores));
//Modify Barrel attribute
chicken.Barrel = null;
Debug.WriteLine("Barrel 1:" + string.Join(",", b1.Stores));
//Remove from stores
b1.Remove(fish);
Debug.WriteLine("Barrel 1:" + string.Join(",", b1.Stores));
输出:
Barrel 1:Fish@Barrel 1,Chicken@Barrel 1
Barrel 1:Fish@Barrel 1
Barrel 1: