5

Person と Seat を含む基本的なシナリオをモデル化しようとしています。Person には Status プロパティがあります: 座っているか立っているか。座席には、現在座っている人を指定する Seated プロパティがあります。また、Seat は、特定の人のみが座ることができるという点で特別です。座席が誰かを「受け入れる」というのは奇妙に聞こえるかもしれませんが、他の人よりも特定の人を好むと想像してみてください。

Tell, Don't Ask 」に続いて、Person オブジェクトと Seat オブジェクトをどのように設計すれば、Seat が彼を "受け入れ" たときにのみ、Person が Seat に座ることができ、ステータスが座っている状態に変更されるようにする必要があります。私が最初に考えたのは、 Person には次のように SitDown メソッドが必要だということでした。

Person.SitDown(Seat seat);

しかし、これは Person クラスがシートに座る前にシートの状態を検査する必要があり、シートの Seated プロパティを更新する必要があるようです (プロパティ自体を更新するシートの代わりに):

// 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 が個人のステータスを変更する必要があります。これは、個人のステータスを更新する方法ですか? 個人だけが自分のステータスを変更できるようにする必要がありますか? この単純なシナリオをどのようにモデル化しますか?

4

6 に答える 6

4

3rd モデルを紹介します... 座席と人の両方を参照する座席。次に、誰かが座るたびにそのモデルのインスタンスを作成し、同じ座席に 2 人が座らないようにするための検証を投入し、タイムアウトを投入することもできます (座席に長時間座っていると、それが失われます)。 .

于 2008-12-25T09:30:06.767 に答える
2

座席サービスが必要なようなにおいがします。それは座席と人を受け入れます。次に、操作を実行できるかどうかを決定します。

そうすれば、その人は、着席していることと場所をマークすることだけに責任を負います。座席は、自分自身を "taken" としてマークすることのみを担当します。

人物と座席が基準を満たしているかどうかを確認するのは、座席サービスの責任です。

于 2013-01-15T18:35:35.617 に答える
1

問題は、モデルが循環依存関係で定義されていることです。これを回避するには 2 つの方法があります。

最初のものは、「Tell, Don't Ask」に厳密に従っているわけではありませんが、要点に近づいています。座ることができるかどうかを調べてから、椅子に座っていることを伝えます。

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

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

これを行うためのより良い方法 (「Tell, Don't Ask」に明確に従います) は、次のようになります。私たちは椅子に座ろうとします。議長が私たちを拒否した場合、私たちは知っています。

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;
    }
}
于 2008-12-25T09:35:44.180 に答える
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;
  }
}

ここにはまだ周期的な依存関係があります。

座席には、座ろうとする人が正当に座れるかどうかを確認する責任があります。Seat は、一度座った人への参照を運びます。座席に座ろうとする方法しか知らない人。

慣例により、successAction は SeatPerson 呼び出しよりも長く保持されるべきではありません。これにより、Seat が Person の状態を損なうことができないことが保証されます。

于 2008-12-25T13:53:18.233 に答える
0

Seat クラスは必要ありません。Seat クラスは、座っている人を追跡します。代わりに、Seat クラスを削除して、Person クラスに isSitting() という名前の新しいメソッドを追加できます。}

于 2015-05-14T09:59:16.053 に答える
-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;
            }
        }
于 2008-12-25T09:34:51.420 に答える