Установка отношений между родителями и детьми в конструкторе без утечки переменной this - PullRequest
1 голос
/ 26 сентября 2019

Я пишу некоторый физический код, который организует объекты в иерархические отношения, где каждый объект класса Body имеет одного родителя (подкласс обрабатывает корневые условия) и ноль для многих детей.Однако, чтобы создать новый Body, я должен добавить его в родительский элемент, и, таким образом, конструктор передает «this» методу addChild своего родителя.

В настоящее время метод body body addChild является закрытым;единственный способ получить доступ к нему за пределами конструктора Body - через Body.setParent.Тем не менее, я обеспокоен тем, что могут быть крайние случаи, в которых это все еще может раскрыть не полностью созданный экземпляр объекта.Приведенный ниже код упрощен только для соответствующих элементов:

import java.util.Set;
import java.util.TreeSet;

public class Body {
    private Body parent;
    private Set<Body> children;

    public Body(Body parent) {
        // instantiates everything else first
        this.children = new TreeSet<Body>;
        this.parent = parent;

        parent.addChild(this);
    }

    public void setParent(Body parent) {
        this.parent.removeChild(this);
        this.parent = parent;
        parent.addChild(this);
    }

    private void addChild(Body child) {
        children.add(child);
    }

    private void removeChild(Body child) {
        children.remove(child);
    }
}

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

1 Ответ

0 голосов
/ 26 сентября 2019

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

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

var newBody = new Body();
newBody.setParent(parent);

Конструктор будет выглядеть такthis.

public Body() {
    this.children = new TreeSet<Body>;
}

И измените метод setParent для проверки отсутствия текущего родителя.

public synchronized void setParent(Body newParent) {
    if (parent != null)
        parent.removeChild(this);
    parent = newParent;
    if (newParent != null)
        newParent.addChild(this);
}

Обратите внимание, что я также изменил имя параметра setParent, чтобы он не конфликтовал с переменной класса,Трудно найти ошибки, возникающие, когда вы забываете использовать «this» для того, чтобы отличить, на какого «родителя» вы ссылаетесь.

Код конструктора, который я удалил, на самом деле был просто дублированием метода setParent.

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

Конечно, есть много способов сделать это.Но это простой способ, который я бы использовал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...