【发布时间】:2012-06-07 15:19:50
【问题描述】:
我的域模型中有几个不同的实体(比如说动物物种),每个实体都有一些属性。这些实体是只读的(它们在应用程序生命周期内不会改变状态)并且它们具有相同的行为(只是属性值不同)。
如何在代码中实现这些实体?
不成功的尝试:
枚举
我试过这样的枚举:
enum Animals {
Frog,
Duck,
Otter,
Fish
}
其他代码段将打开枚举。然而,这会导致难看的切换代码,分散逻辑和problems with comboboxes。没有漂亮的方法可以列出所有可能的动物。不过,序列化效果很好。
子类
我还考虑了每种动物类型是公共基础抽象类的子类的位置。但是,Swim() 对所有 Animals 的实现都是相同的,所以它没有什么意义,并且可序列化现在是一个大问题。由于我们代表一种动物类型(物种,如果你愿意的话),每个应用程序都应该有一个子类实例,当我们使用序列化时,维护起来既困难又奇怪。
public abstract class AnimalBase {
string Name { get; set; } // user-readable
double Weight { get; set; }
Habitat Habitat { get; set; }
public void Swim(); { /* swim implementation; the same for all animals but depends uses the value of Weight */ }
}
public class Otter: AnimalBase{
public Otter() {
Name = "Otter";
Weight = 10;
Habitat = "North America";
}
}
// ... and so on
简直糟透了。
静态字段
This blog post 给了我一个解决方案的想法,其中每个选项都是类型内的静态定义字段,如下所示:
public class Animal {
public static readonly Animal Otter =
new Animal
{ Name="Otter", Weight = 10, Habitat = "North America"}
// the rest of the animals...
public string Name { get; set; } // user-readable
public double Weight { get; set; }
public Habitat Habitat { get; set; }
public void Swim();
}
那太好了:您可以像枚举 (AnimalType = Animal.Otter) 一样使用它,您可以轻松添加所有已定义动物的静态列表,您有一个明智的地方来实现 Swim()。可以通过保护属性设置器来实现不变性。但是有一个主要问题:它破坏了可序列化性。一个序列化的 Animal 必须保存它的所有属性,并且在反序列化时它会创建一个 Animal 的新实例,这是我想避免的。
有没有一种简单的方法可以使第三次尝试成功?对于实施这样的模型还有什么建议吗?
【问题讨论】:
-
我会选择子类,我不明白序列化是一个大问题和单个实例。您可以使用依赖注入。
-
如果有多个实例代表同一事物,则必须考虑相等条件。当两种动物类型相等时?如果名字一样呢?如果我将以前版本中的序列化名称与当前版本中的名称进行比较会怎样?
-
所有解决方案都有相同的序列化问题。它应该由序列化逻辑处理。子类更适合您的应用程序的测试、封装和未来扩展。
-
@Dominik:你是说如果你把
Otter的名字从Otter改成Sea Otter,那么你还是希望旧实例反序列化为Otter——即使他们有不同的名字? -
@Gabe:如果我将
Otter的名称更改为Sea Otter,我希望将所有旧实例反序列化为Sea Otter- 新名称。
标签: c#