2011-12-21 3 views
3

У меня есть быстрый вопрос об организации конкретной проблемы ООП.Наилучшее решение проблемы организации ООП

Скажем, у меня есть класс ландшафта, полный плиток. Существует несколько производных класса Tile, а именно Door. Класс Door имеет метод open(), который открывает дверь, и close(), который закрывает дверь. Это имеет смысл до тех пор, пока оба этих метода не должны что-то проверять перед открытием и/или закрытием. Как я могу сделать проверку двери для объекта, не зная о его родительском?

Простым решением было бы проверить что-то в пути до вызова open(), но если бы была дверь другого типа, которая должна была быть проверена в другой форме, это создавало бы беспорядок на более высоком уровне.

Кажется, у этого был бы простой ответ, но также кажется, что я сталкиваюсь с этой проблемой чаще, чем нет.

+3

Двери неактивны, обработчик открывает и закрывает их, и именно этот обработчик должен проверить, заблокирована ли дверь/заблокирована/уже в состоянии, в котором она хочет. Дверь знает только о себе, а не о других вещах в ее среде. – slashmais

+0

@slashmais Итак, мое решение правильно? – lowq

+0

Да, выглядит правильно - разные обработчики будут иметь разные возможности в том, как они приближаются к дверям; например: вы разблокируете и откройте дверь своего дома, полицейские выбьют его, автоматическое устройство сделает это и т. д. – slashmais

ответ

2

Один ответ заключается в том, что двери должны знать, как открывать и закрывать себя и знать, заблокированы ли они. Если дверь является классом, то оба состояния ( is_open, is_blocked) и поведение ( open_the_door, close_the_door) должны находиться в классе двери. Инкапсуляция является фундаментальным принципом объектно-ориентированной парадигмы.

Но реальный ответ обычно более тонкий. Можете ли вы дать некоторое представление о приложении и что ему нужно выполнить? Существуют чистые, простые решения, которые будут хорошо работать для игрушечных приложений, но большие приложения нуждаются в чем-то более сложном.

Как обращаться с дверью is_blocked представляет некоторые проблемы с дизайном. Нет ни одного правильного дизайна, но есть хороший дизайн и плохие конструкции. Отделить хорошие идеи от плохих идей зависит не только от принципов проектирования - это зависит от контекста проблемы.

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

  • Игры часто имеют главный объект под названием «Игра» или «Совет» или «Карта». Пусть главный объект хранит коллекцию вещей в иерархии плитки (плитки, двери и т. Д.).

  • Пусть главный объект также содержит коллекцию вещей, которые могут блокировать двери или иным образом взаимодействовать с плитами и дверями.

  • Теперь создайте метод с именем update() в классе Tile, который принимает объект как параметр.

  • И создать логический атрибут для класса Door, который называется «заблокирован». Метод обновления для двери может сделать примерно следующее:

    Door::update(BlockingObject object) { 
    if(object.location == this.location) 
         blocked = true 
    }

  • The method on the superclass of door might do nothing. Like this:

    Tile::update(BlockingObject obj) { 
        //tiles cannot be blocked 
    }

  • Now, inside the game loop, include a step where all the doors are set to blocked = false.

  • Чтобы создать некоторые циклы, попросите все плитки проверить, заблокированы ли они.Это может выглядеть примерно так, как это в псевдокоде:

    For each tile { 
        For each blocking object { 
          tile.update(object) 
        } 
    }

  • Это наивно, но прямой дизайн, который справедливо для парадигмы ОО.

  • Дизайн дает плитки/двери и объекты возможность взаимодействовать один раз за ход, не заставляя их удерживать ссылки друг на друга.

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

Отличный дизайн?

Ответ зависит от потребностей приложения.

+0

Да. Это определенно игра. Мне нравится ваше решение, но 'update (BlockingObject)' будет выглядеть как функция, которая будет находиться только на двери и не должна применяться к другим фрагментам. Я также мог видеть только обновление окружающих плиток, когда плитка была добавлена ​​или удалена для скорости. – lowq

Смежные вопросы