Один из ответов заключается в том, что двери должны знать, как открываться и закрываться, и знать, заблокированы ли они. Если Door - это класс, то и состояние ( is_open , is_blocked ) и поведение ( open_the_door , close_the_door ) должны находиться в Дверной класс. Инкапсуляция является фундаментальным принципом объектно-ориентированной парадигмы.
Но реальный ответ обычно более тонкий. Можете ли вы предоставить некоторые сведения о приложении и о том, что ему нужно для этого сделать? Есть чистые, простые решения, которые хорошо подойдут для игрушечных приложений, но более крупным приложениям потребуется нечто более сложное.
Как обращаться с дверью is_blocked представляет некоторые проблемы дизайна. Нет единого правильного дизайна, но есть хороший дизайн и плохой дизайн. Отделение хороших идей от плохих идей зависит не только от принципов проектирования - это зависит от контекста проблемы.
Если бы мне пришлось угадывать, я бы предположил, что ваше приложение - игра. Возможно, плитки представляют область игрового поля или карты. Вы определили, что многим различным объектам, возможно, придется взаимодействовать, и что будет беспорядок, если они все ссылаются друг на друга напрямую.
В играх часто есть главный объект, который называется «Игра», «Доска» или «Карта». Пусть главный объект содержит коллекцию вещей в иерархии плиток (плитки, двери и т. Д.).
Пусть главный объект также содержит коллекцию вещей, которые могут блокировать двери или иным образом взаимодействовать с плитками и дверями.
Теперь создайте метод с именем update () в классе Tile, который принимает объект в качестве параметра.
И создайте логический атрибут для класса Door, который называется «заблокирован».
Метод обновления для двери может сделать что-то вроде этого:
<pre>Door::update(BlockingObject object) {
if(object.location == this.location)
blocked = true
}
Метод надкласса двери может ничего не делать. Как это: <pre>Tile::update(BlockingObject obj) {
//tiles cannot be blocked
}
Теперь внутри игрового цикла включите шаг, в котором все двери установлены на blocked = false
.
Циклы создания некоторых просят все плитки проверить, не заблокированы ли они. Это может выглядеть примерно так в псевдокоде:
<pre>For each tile {
For each blocking object {
tile.update(object)
}
}
Это наивный, но прямой дизайн, который соответствует парадигме ОО.
Дизайн дает плиткам / дверям и объектам возможность взаимодействовать один раз за ход, не заставляя их хранить ссылки друг на друга.
Дизайн будет хорошо работать для нескольких сотен плиток и объектов, но он будет очень медленным для тысяч плиток.
Это хороший дизайн?
Ответ зависит от потребностей приложения.