问题描述
|
我设计了一个类,其中包含有关给定对象的一些信息,这些信息将在sql Server数据库中注册。我想使该对象(深层)不可变,但我还必须确保该对象仅被注册一次。如果此对象实现以下模式,是否仍可以认为它是不可变的?
public class NewClass
{
private bool registered;
public string SomeProperty { get; private set; }
public NewClass Register()
{
if (registered)
{
throw new NotImplementedException(/*arguments*/);
}
/* Register on DB here... */
registered = true;
return new NewClass(somePropertyFromDB);
}
public NewClass(string someProperty)
{
registered = false;
SomePropery = someproperty;
}
}
我要说的是,除了布尔字段registered
以外,该对象是不可变的,但是此字段使我有些疑问,因为它实际上在第一次执行Register
方法时就会发生变化。有人可以告诉我如何解决此问题。仍然使对象不可变?
解决方法
不,这绝对不是一成不变的。
registered
值在对象的整个生命周期内变化。
为了使它不可变,您必须不允许registered
字段在对象的整个生命周期内发生变化-而是让Register
返回一个新对象,该对象的值等于registered
的true
。
我还要删除SomeProperty
的私有设置器,只是有一个getter和一个readonly变量。
所以像这样:
public class NewClass
{
private readonly bool registered;
private readonly string someProperty;
public bool Registered { get { return registered; } }
public string SomeProperty { get { return someProperty; } }
public NewClass Register()
{
// Note the change of exception here
if (registered)
{
throw new InvalidOperationException(\"Already registered\");
}
return new NewClass(somePropertyFromDB,true);
}
// You may want to have a public constructor with just someProperty
// which calls this one,which you could make private
public NewClass(string someProperty,bool registered)
{
this.registered = registered.;
this.someProperty = someproperty;
}
}
一些注意事项:
另一种选择是拥有两个独立的类,分别为RegisteredFoo
和UnregisteredFoo
;使用该类可能会更容易理解代码
没有什么可以阻止某人两次叫Register
的,所以使这种不变性对幂等性没有真正的帮助。由于存在自然的副作用(与数据库对话),因此很难使其真正发挥作用。