我觉得造型有点不对劲。 Mother 和 Child 在语义上彼此相关,但它们是同一对象的实例。他们都是Person。
Person 的创建是由Person 执行的操作。所以Person 甚至不应该有一个公共构造函数,而是一个负责这个逻辑的工厂方法。像这样的:
public class Person : ObservableObject
{
private Person()
{
Children = new ObservableCollection<Person>();
}
public Person Mother { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
public Person Procreate()
{
var child = new Person();
child.Mother = this;
this.Children.Add(child);
return child;
}
}
这种建模还是有点局限,例如我们这里只讨论无性繁殖。所以我们还没有有效地模拟人类。也许我们需要添加一个父亲?
public class Person : ObservableObject
{
private Person()
{
Children = new ObservableCollection<Person>();
}
public Person Mother { get; private set; }
public Person Father { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
public Person Procreate(Person father)
{
var child = new Person();
child.Mother = this;
child.Father = father;
this.Children.Add(child);
father.Children.Add(child);
return child;
}
}
我们当然会想要添加一些检查空值和诸如此类的东西。现在我们还发现我们需要指定性别。 (虽然家庭结构可能有很大差异,但创造一个人的行为已经很成熟了。)所以我们可以继续添加这样的功能。在某些时候,我们可能确实对这些进行了子类化,但这些子类最终可能主要是语义传递对象,具有此 Person 超类的硬编码默认值。
但只是为了好玩,让我们尝试添加性别...
public class Person : ObservableObject
{
private Person(Sex gender, Person mother, Person father)
{
// TODO: Check for null mother and father
this.Gender = gender;
this.Mother = mother;
this.Father = father;
Children = new ObservableCollection<Person>();
}
public Sex Gender { get; private set; }
public Person Mother { get; private set; }
public Person Father { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
public Person Procreate(Person father)
{
// TODO: Check for null father, confirm gender of father
var child = new Person(PickRandomGender(), this, father);
this.Children.Add(child);
father.Children.Add(child);
return child;
}
private Sex PickRandomGender() { /.../ }
public enum Sex
{
Female,
Male
}
}
好的,这很有趣。通过将一些逻辑移动到构造函数也进行了一些清理。但现在还有另一个问题……父亲可以生育。这听起来有点痛苦。现在看起来我们已经准备好进行子类化了:
public class Person : ObservableObject
{
protected Person(Sex gender, Person mother, Person father)
{
// TODO: Check for null mother and father
this.Gender = gender;
this.Mother = mother;
this.Father = father;
Children = new ObservableCollection<Person>();
}
public Sex Gender { get; private set; }
public Person Mother { get; private set; }
public Person Father { get; private set; }
public ObservableCollection<Person> Children { get; private set; }
protected Sex PickRandomGender() { /.../ }
public enum Sex
{
Female,
Male
}
}
public class Woman : Person
{
// TODO: Override Gender with a hard-coded value
public Person Procreate(Person father)
{
// TODO: Check for null father, confirm gender of father
var child = new Person(PickRandomGender(), this, father);
this.Children.Add(child);
father.Children.Add(child);
return child;
}
}
(我们是否也应该将Man 子类化?它在语义上看起来更清晰,但有没有女性不共享的男性特有的操作或属性?也许吧,但我们的模型还没有那么详细。)
回想起来,Mother 和 Child 的类在这一点上似乎有点局限和短视。女人不一定是母亲,所有人都是孩子。您可以想象,有很多功能可以添加到这个系统中。但是按照同样的一般过程来构建这样的域应该可以适应这种情况。