Как я могу понять концепцию чистого ООД? - PullRequest
5 голосов
/ 23 апреля 2011

У меня все еще есть небольшая проблема с пониманием концепции чистого ООД.

Допустим, у нас есть класс Human, и мы живем в мире, где иногда люди гуляют (мозг управляет ногами), где иногда исчезают деревья (человек это замечает), а иногда люди случайно бьют друг друга.

Первые два случая действительно просты:

class Tree {
  private:
    void disappear()
    {
       // call onTreeDisappeared() for all human observers
    }
};

class Human {
  public:
    // The human notices that a tree disappeared
    void onTreeDisappeared();
  private:
    int x, y, z;
    // Human wants to walk forward
    void moveForward();
    // Hit another human, possibly causing him to fall down
    void hit(Human &target);
};

Теперь у меня действительно плохая проблема с методом удара. Конечно, приятно, что ты можешь сказать

anna.hit(bob);

До сих пор я думаю, что это хорошо (пожалуйста, пожаловайтесь, если что-то не так) и читается как проза (что должно быть в хорошем коде ООП). Но как перенести попадание в ООП? Если Анна бьет Боба, а Боб падает, то падение не вызвано ни Анной, ни Бобом. Это вызвано попаданием, потерей баланса и физикой.

Я знаю только 2 варианта для этого случая, но почему-то я думаю, что оба отстой:

public: void fallDown()
{ z = 0; }

public: void hit(Human &target)
{
  bool targetFallsDown = true; // could be random or any algorithm you like
  if(targetFallsDown)
  { target.fallDown(); }
}

В этом случае Анна "падает" Боб. Но это совершенно не имеет никакого смысла. Это не значит, что Анна хватает тело Боба и двигает его к земле. Но есть и другой вариант:

private: void fallDown()
{ z = 0; }

public: void onHitCausesMeToFallDown()
{ fallDown(); }

public: void hit(Human &target)
{
  bool targetFallsDown = true; // could be random or any algorithm you like
  if(targetFallsDown)
  { target.onHitCausesMeToFallDown(); }
}

В этом случае тело Боба «замечает», что удар заставляет его упасть на землю, затем он «переместится» на землю. Я думаю, что это лучше, чем первый вариант, но это все равно почему-то не так.

Так что, пожалуйста, умные люди ООП, объясните мне, как вы справляетесь со случаями, когда в реальном мире А изменяет состояние B, но в мире ООП только B должен изменять состояние B.

Ответы [ 2 ]

10 голосов
/ 23 апреля 2011

Я думаю, что вы попадаете в ловушку, пытаясь смоделировать «реальный» мир в классах, не имея цели для вашего дизайна.

Что должна делать ваша программа ? Как только вы это разработали, вы можете приступить к разработке того, какие аспекты реального мира вы хотите моделировать, а какие части реального мира не имеют значения и не нуждаются в моделировании. Создание карты классов для конкретного типа объекта реального мира просто потому, что ее легко визуализировать, часто является ошибкой. Вам нужно только смоделировать понятия, которые важны для вашей программы.

OOD подразумевает использование таких методов, как абстракция и полиморфизм, чтобы объекты могли взаимодействовать друг с другом, не зная о реализации друг друга.

В вашей реализации вам нужно решить, какое поведение вы хотите смоделировать и какие знания хочет каждый объект. Например, вы можете захотеть, чтобы человек определился с тем, хочет ли он упасть, в зависимости от того, насколько сильно его ударили.

void Human::receiveHit(Hit hit)
{
    if (hit.IsBigForThisWeight(this->weight))
        this->fallDown();
}

Обратите внимание, что вещь, которая поражает меня, не должна знать или заботиться о том, какое влияние она окажет на меня. Это моя реакция на удар. Я также смоделировал объект «попадания», потому что это имеет смысл для моей программы. Все может поразить меня, создав объект Hit и заставив меня его получить. В будущем меня могут сбить автобус или поезд без каких-либо изменений в моем классе.

1 голос
/ 23 апреля 2011

Я думаю, что ваша дилемма возникает из-за того, что вы не моделируете течение времени. Все происходит сразу, когда вы делаете anna.hit(bob).

Если вы смоделировали свои сущности как управляющие их собственными конечными автоматами, тогда все станет больше похоже на реальность:

  1. anna.hit (bob) вызывает изменение состояния боба на falling.

  2. В течение следующих нескольких циклов Боб продолжает падать в своем falling состоянии.

  3. Со временем состояние Боба меняется на on_ground.

  4. Затем состояние Боба изменится на cries_for_mommy.

Проверьте шаблон проектирования State для идей о том, как реализовать начальные диаграммы на языке OO. В этой теме рассматривается книга «Банды четырех» Design Patterns .

...