OOP composition
本文关键字:composition OOP | 更新日期: 2023-09-27 18:33:47
我有一个关于OOP组合的问题。
假设一个母亲有 0 个或更多的孩子,一个孩子有一个且只有一个亲生母亲。
为了说明这一点,我做了以下工作:
public class Mother : ObservableObject
{
// [...]
ObservableCollection<Child> Children {get; set;}
}
public class Child : ObservableObject
{
public Child(Mother mother)
{
this.Mother = mother;
// Adding the child to the mother's children collection
mother.Children.Add(this);
}
public Mother Mother {get; set;}
}
但我想知道是否可以自动将孩子添加到母亲的收藏中,或者我是否应该使用以下:
Mother mother = new Mother();
Child child = new Child(mother);
mother.Children.Add(child);
谢谢:)
我宁愿,
public class Mother : ObservableObject
{
// ...
public Child GiveBirth()
{
var newBorn = new Child(this);
this.Children.Add(newBorn);
return newBorn;
}
// ...
}
我认为建模有点不对劲。 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
的阶级在这一点上似乎有点有限和短视。 女人不一定是母亲,所有人都是孩子。 可以想象,该系统可以添加许多功能。 但是,遵循像这样构建域的相同一般过程应该可以适应这一点。
假设您有一个类名构建。这个类构建有一个名为 BuildRooms(( 的函数。还有另一个班级房间,具有制作房间的功能。您将类 Room 的对象创建为 r1、r2、r3 等。现在这栋楼有3个房间。我们可以在 Room 类中打开门和关门方法。建筑类由房间组成。这意味着这栋楼有3个房间。用您喜欢的任何语言编写代码。这是构图。建筑有房间,所以它是Has-A关系。
class building{
void make_rooms()
{
room r1=new room(), r2=new room();
r1.open();
r2.close();
}
}
class room{
void open()
{
}
void close()
{
}
}