Неявные против явных структур данных - PullRequest
1 голос
/ 28 июля 2011

В последнее время я боролся с некоторой повторяющейся проблемой проектирования, которую я не знаю, как элегантно решить.

Скажем, я делаю игру с парой игроков, и для каждого игрока есть несколько связанных фигур. Вместе эти части образуют полусложную коллекцию или структуру. Теперь я мог реализовать эту структуру двумя способами: либо неявно хранить структуру с помощью указателей в самих частях, то есть:

class BigPiece extends Piece {
    Piece opposingPiece, nextPiece, previousPiece, index;
}

Или я мог бы реализовать эту структуру в классе коллекции и сохранить информацию централизованной:

class SomeCollection<Collection<Piece>> {
    SomeOtherCollection<Collection<Piece>> collection 
        = new SomeOtherCollection<Collection<Piece>>();

    public SomeCollection() {
        collection.add(new PieceCollection<Piece>();
        collection.add(new PieceCollection<Piece>();
        collection.add(new PieceCollection<Piece>();
    }

    public Piece getPiece(int playerIndex, int pieceIndex) {
        collection.get(playerIndex).get(pieceIndex);
    }

    public Piece getOpposingPiece(int playerIndex, int pieceIndex) {
        int nextPlayerIndex = collection.listIterator(playerIndex).nextIndex();
        return this.collection.get(nextPlayerIndex).get(pieceIndex);
    }
}

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

Проблема, с которой я обычно сталкиваюсь при первом решении, заключается в том, что вам все равно нужно создавать ассоциации в каком-либо сборщике или фабрике, которые фактически связывают объекты вместе. Это не кажется мне надежным. Кто может заверить меня, что все указатели на самом деле верны в течение всего срока службы приложения?

Второе решение централизует данные больше. Это действительно ослабляет более высокие классы (такие как отдельные части). Проблема, с которой я обычно сталкиваюсь, заключается в том, что всякий раз, когда я хочу просмотреть эту коллекцию, я должен сделать это на более низком уровне. Вы не можете спросить фигуру «Эй, какая у вас фигура противника?». Нет, вам нужно получить игровой объект, чтобы получить указатель на вашу коллекцию, который вы затем спросите, что является противоборствующим элементом. Это делает больше «управляемых» классов, которые собирают данные со всего вашего приложения (метод chaining = () для окончательной реализации вашего алгоритма. Это, кажется, нарушает Закон Деметры .

Конечно, я мог бы добавить указатель на соответствующую коллекцию для каждого отдельного предмета, но я не знаю, хорошая ли это идея, поскольку это только дублирующая информация.

1 Ответ

0 голосов
/ 28 июля 2011

Моя личная рекомендация является более вторым вариантом, чем первым. Как вы указали, часть не должна (по крайней мере, в этом контексте) знать, какова ее противоположная / следующая / предыдущая часть.

Управляющий класс будет иметь более логичный смысл для более удобного взаимодействия между классами, а не с частями, имеющими ссылки на другие части. Я признаю, что не полностью знаю Закон Деметры, но Википедия заставляет меня поверить, что все дело в инкапсуляции, в которой классы менеджера также могут помочь!

Я не думаю, что Части (опять же, в этом контексте) должны быть в состоянии, скажем, переместить другую фигуру. Однако класс менеджера будет логически желать.

Это мое предложение, надеюсь, оно поможет!

...