简单的场景,如何融入“告诉不要问”?

发布于 2024-07-11 00:17:39 字数 993 浏览 6 评论 0原文

我正在尝试对涉及人员和座位的基本场景进行建模。 一个人有一个状态属性:坐着或站立。 座位有一个 Seated 属性,用于指定当前坐在座位上的人。 此外,座位的特殊之处在于它只“接受”某些人坐在其中。 我知道席位“接受”某人听起来很奇怪,但想象一下它比其他人更喜欢某些人。

遵循“告诉,不要问”,我应该如何设计人员和Seat 对象使得只有当 Seat“接受”某人并且他的状态更改为 Sitting 时,该人才能坐在该 Seat 上。 我的第一个想法是,一个人应该有一个 SitDown 方法,如下所示:

Person.SitDown(Seat seat);

但这似乎需要 Person 类在坐下之前检查座位的状态,并且必须更新座位的 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;
    }
}

但这仍然需要 Seat 来更改该人的状态。 这是应该更新此人的状态的方式吗? 难道只有一个人才能改变他的地位吗? 您将如何模拟这个简单的场景?

I'm trying to model a basic scenario involving a Person and a Seat. A Person has a Status property: Sitting or Standing. A seat has a Seated property that specifies the Person that is currently sitting in it. Also, a Seat is special in that it only "accepts" certain people to sit in it. I know it sounds strange for a Seat to "accept" someone, but just imagine it prefers certain people over others.

Following "Tell, Don't Ask," How should I design the Person and Seat objects so that a Person can sit down in a Seat only when the Seat "accepts" him and also have his status changed to Sitting. My first thought was that a Person should have a SitDown method as follows:

Person.SitDown(Seat seat);

But this seems like it would require the Person class to inspect the state of the Seat before sitting in it, as well as having to update the Seat's Seated property (instead of the Seat updating the property itself):

// inside the Person class
void SitDown(Seat seat) {
    if (seat.AcceptsPlayer(this)) {
        seat.Seated = this;
        this.Status = Sitting;
    }
}

It seems better to have the Seat class handle seating a person:

Seat.SeatPerson(Person person);

// inside Seat class
void SeatPerson(Person person) {
    if (IsAccepted(person)) {
        this.Seated = person;
        person.Status = Sitting;
    }
}

But this still requires the Seat to change the person's status. Is this the way that the person's status should be updated? Should only a Person be able to change his status? How would you model this simple scenario?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

堇色安年 2024-07-18 00:17:39

引入第三个模型……既涉及座位又涉及人员的座位。 然后,您可以在每次有人坐下时创建该模型的实例,添加一些验证以防止两个人坐在同一个座位上,甚至可能添加一些超时(如果您坐在座位上的时间太长,您就会失去它) 。

Introduce a 3rd model... Seatings that has a reference to both the seat, and the person. Then you can create an instance of that model every time someone sits down, throw in some validations for preventing two people sitting in the same seat, and maybe even throw in some timeouts (if your sitting in a seat too long, you lose it).

空名 2024-07-18 00:17:39

闻起来像是你需要座位服务。 它可以容纳一个座位和一个人。 然后决定是否可以进行手术。

这样,该人只需负责将自己标记为就座和位置。
该席位只负责将自己标记为“已占用”。

检查人员和座位是否符合标准是座位服务部门的责任。

Smells like you need a seating service. That accepts a seat and a person. Then decides if the operation can happen.

That way the person is only be responsible for marking itself as seated and where.
The seat is only responsible for marking itself as "taken".

It's the seating service responsibility to check if the person&seat met the criteria.

ぇ气 2024-07-18 00:17:39

问题是您的模型是用循环依赖定义的。 有两种方法可以避免这种情况。

第一个并没有明确遵循“告诉,不要问”,但它更接近要点。 我们试着看看是否可以坐下,然后告诉椅子我们坐在上面。

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;
    }
}

The problem is your model is defined with a circular dependency. There are two ways of avoiding this.

The first one doesn't exactly follow "Tell, Don't Ask" explicitly, but it gets closer to the point. We try to find out if we can sit down, then tell the chair that we're sitting in it.

void Person.SitDown(Seat seat) {
    if (seat.AcceptsPlayer(this)) {
        seat.SeatPerson(this);
        this.Status = Status.Sitting;
    }
}

void Seat.SeatPerson(Person person) {
    this.Seated = person;
}

A better way to do this (which follows the "Tell, Don't Ask" more explicitly) might be the following. We try to sit in the chair. If the chair rejects us, we know.

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;
    }
}
早茶月光 2024-07-18 00:17:39

使用回调,以便每个类都可以维护它负责的状态。

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 的状态。

Use a callback so that each class can maintain the state that it is responsible for.

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;
  }
}

There's still cyclical dependency here.

Seat has a responsibility to check that the person attempting to sit is valid to do so.
Seat carries a reference to the person once they have sat.
Person only knows a method to try to sit in a seat.

By convention, successAction should not be held on to longer than the SeatPerson call. This guarantees that Seat cannot compromise the state of Person.

物价感观 2024-07-18 00:17:39

您不需要 Seat 类。
Seat 类跟踪坐着的人。
相反,您可以删除 Seat 类并在 Person 类中添加一个名为 isSitting() { return this.Status == Sitting; 的新方法; }

You don't need the Seat class.
The Seat class keeps track of the person who is sitting.
Instead you can remove the Seat class and add a new method in the Person class named isSitting() { return this.Status == Sittting; }

物价感观 2024-07-18 00:17:39

让该人尝试坐在座位上,并根据操作的成功更新其状态:

只需调用 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;
            }
        }

let the person try to seat on the seat, and update it's state depending on the success of the operation:

Just call myPerson.TrySeat(targetseat), which returns true if the sitting process succeeded.

//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;
            }
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文