在部分可变类中,将可变字段与其不可变字段混合,还是创建一个封装它们的新类(或类)更好?这是我正在谈论的C#中的一个例子:
interface IBedroom
{
int Volume { get; }
string Color { get; }
void Paint(string newColor);
}
这是一个在其字段中具有混合可变性的实现:
class MixedMutabilityBedroom : IBedroom
{
readonly int volume;
string color;
public MixedMutabilityBedroom(int volume, string color = "")
{
this.volume = volume;
this.color = color;
}
public int Volume
{
get { return volume; }
}
public string Color
{
get { return color; }
}
public void Paint(string newColor)
{
color = newColor;
}
}
另一个具有不同的可变性:
// first, a fully mutable helper class
class RoomColor
{
string value;
public RoomColor(string value)
{
this.value = value;
}
public string Value
{
get { return value; }
}
public void Change(string newValue)
{
value = newValue;
}
}
和分离的可变性实现:
class SeparatedMutabilityBedroom : IBedroom
{
readonly int volume;
readonly RoomColor color;
public SeparatedMutabilityBedroom(int volume, RoomColor color)
{
this.volume = volume;
this.color = color;
}
public int Volume
{
get { return volume; }
}
public string Color
{
get { return color.Value; }
}
public void Paint(string newColor)
{
color.Change(newColor);
}
}
我个人支持后者的风格。根据我的经验,在并发场景中由状态操作引起的错误很难调试。随着并发性成为程序的标准,似乎本地化可变性是减少调试工作的关键因素。在第二个示例中,我们不必查看整个类实现以找出操作状态的位置。 SeparatedMutabilityBedroom
的全部可变性已本地化为RoomColor
。
答案 0 :(得分:0)
使用不可变数据结构进行编程是一种非常有用的技术,但很难对基于简单示例的整体最佳实践或建议进行批评。确定什么是最好的必须考虑其他因素,例如如何使用这个类并与之交互。
但是,假设您处于具有大量并发性且具有此对象的多个编写器的情况下,那么使对象部分不可变实际上不会对您造成太大影响,因为您仍然会遇到问题。
在这种情况下,要么使用某种同步原语,要么使用完全不可变的对象。
这个answer讨论了使用完全不可变对象的一些技巧。