我正在尝试模拟涉及人员和座位的基本情景。人具有身份属性:坐着或站立。一个席位有一个Seated属性,用于指定当前位于其中的Person。此外,座位特殊,因为它只“接受”某些人坐在其中。我知道座位“接受”某人听起来很奇怪,但只是想象它更喜欢某些人而不是其他人。
在“Tell, Don't Ask之后,”我应该如何设计人物和座位对象,以便只有当座位“接受”他并且他的状态改为“坐着”时,人才可以坐在座位上。我的第一个想法是一个Person应该有一个SitDown方法如下:
Person.SitDown(Seat seat);
但这似乎需要Person类在坐之前检查Seat的状态,以及必须更新Seat的Seated属性(而不是更新属性本身的Seat):
// inside the Person class
void SitDown(Seat seat) {
if (seat.AcceptsPlayer(this)) {
seat.Seated = this;
this.Status = Sitting;
}
}
最好让Seat类处理一个人:
Seat.SeatPerson(Person person);
// inside Seat class
void SeatPerson(Person person) {
if (IsAccepted(person)) {
this.Seated = person;
person.Status = Sitting;
}
}
但这仍然要求座位改变此人的身份。这是该人的状态应该更新的方式吗?只有一个人能够改变他的身份吗?你会如何模拟这个简单的场景?
答案 0 :(得分:4)
介绍第3个模型......座位既包含座位,也包含人物。然后你可以在每次有人坐下时创建该模型的实例,投入一些验证以防止两个人坐在同一个座位上,甚至可能会抛出一些超时(如果你坐在座位上太长时间,你会失去它)
答案 1 :(得分:2)
闻起来像你需要一个座位服务。接受一个座位和一个人。然后决定是否可以进行操作。
这样,这个人只负责将自己标记为坐着和在哪里。 该座位仅负责将自己标记为“已拍摄”。
检查座位和座位是否符合标准是座位服务的责任。
答案 2 :(得分:1)
问题是您的模型是使用循环依赖项定义的。有两种方法可以避免这种情况。
第一个并没有明确地遵循“告诉,不要问”,但它更接近于这一点。我们试着找出我们是否可以坐下来,然后告诉主席我们坐在里面。
void Person.SitDown(Seat seat) {
if (seat.AcceptsPlayer(this)) {
seat.SeatPerson(this);
this.Status = Status.Sitting;
}
}
void Seat.SeatPerson(Person person) {
this.Seated = person;
}
更好的方法(更明确地遵循“告诉,不要问”)可能如下。我们试着坐在椅子上。如果主席拒绝我们,我们知道。
void Person.SitDown(Seat seat) {
if (seat.SeatPerson(this)) {
this.Status = Status.Sitting;
}
else
{
//Couldn't sit down!
}
}
bool Seat.SeatPerson(Person person) {
if (this.IsAccepted(person) && this.Seated == null) {
this.Seated = person;
return true;
}
else
{
return false;
}
}
答案 3 :(得分:1)
使用回调,以便每个类都可以维护它负责的状态。
public class Seat
{
public void SeatPerson(Person person, Action successAction)
{
if (IsAccepted(person))
{
this.Seated = person;
successAction();
}
}
}
public class Person
{
public void Sit(Seat seat)
{
seat.SeatPerson(this, this.SitComplete);
}
public void SitComplete()
{
this.Status = Sitting;
}
}
这里仍然存在周期性依赖。
席位有责任检查尝试坐着的人是否有效。 一旦他们坐下,座位就会引用该人。 人只知道一种试图坐在座位上的方法。
按照惯例,successAction不应该保持比SeatPerson调用更长的时间。这保证了Seat不会危及Person的状态。
答案 4 :(得分:0)
您不需要Seat课程。 Seat类跟踪坐着的人。 相反,你可以删除Seat类并在Person类中添加一个名为isSitting()的新方法{return this.Status == Sittting; }
答案 5 :(得分:-1)
只需调用myPerson.TrySeat(targetseat),如果坐着的过程成功,则返回true。
//inside Person class
public bool TrySeat(Seat seat)
{
if (seat.TrySeat(this))
{
Status = Sitting;
return true;
}
else
{
return false;
}
}
//inside Seat class
internal bool TrySeat(Person person)
{
if (CanSeat(person))
{
Seated = person;
return true;
}
else
{
return false;
}
}