«Утечка» с точки зрения дизайна - PullRequest
2 голосов
/ 23 ноября 2011

Предупреждение: утечка "this" в конструкторе

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

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

Допустим, мне нужен кадр, который имеет и имеет список (Frame)(Список списка)).В List я могу захотеть сделать что-то, например add ().Чтобы убедиться, что Frame знает как можно меньше о List (только то, что он есть), я бы хотел получить доступ к содержащему Frame из списка (List HAS a Frame?).Это кажется немного глупым, но у меня есть 2+ реализации List, которые будут использовать Frame по-разному.

Чтобы убедиться, что мой код используется правильно, мне понадобится Frame в конструкторе List.Я бы также потребовал List в конструкторе Frame, так как он ДОЛЖЕН иметь один:

public abstract class Frame {
    private final List list;

    public Frame(List list) {
        this.list = list;
        list.setFrame(this);
    }
}

public abstract class List {
    private Frame frame;

    protected final void setFrame(Frame frame) {
        this.frame = frame;
    }
}

Итак, это плохой дизайн, или я действительно должен создать какой-нибудь промежуточный каркас, который это делает, или даже оставитьлеса для пользователя?

Спасибо!

Ответы [ 2 ]

5 голосов
/ 23 ноября 2011

Введите заводской метод:

public static Frame createFrame(List list) {
    Frame frame = new Frame(list);
    list.setFrame(frame);
}

private Frame(List list) {
    this.list = list;
}

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

1 голос
/ 13 декабря 2011

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

Поначалу немного сложно понять, почему двойное связывание не такая уж хорошая идея, но вот несколько причин:

  1. В структуре с четкими отношениями родитель-потомок тривиально использовать одни и те же дочерние объекты более чем в одном родительском элементе. С другой стороны, в структуре с двойной связью, если вы хотите создать новую структуру, которая разделяет некоторые элементы из оригинала, вы должны либо создать новые копии интересующих элементов, либо вы должны уничтожить оригинал структура.
  2. Существует много шаблонов проектирования, которые основаны на четкой цепочке «команд» в графе объектов, и двойные структуры скрывают эту цепочку команд от читателей кода.
  3. Во многих случаях обработка дочернего элемента требует знания родителя, в котором этот дочерний элемент появляется, лучше обрабатывать, передавая родительский параметр в качестве аргумента «контекста» методу, который обрабатывает дочерний элемент. Классический пример этого шаблона - в интерпретаторах, где оценка выражения принимает в качестве аргумента «среду», которая содержит всю внешнюю информацию, необходимую для оценки дочернего выражения. (Или, в качестве альтернативы, вы используете сохраняющий итератор или иерархический посетитель, который перемещается по структуре и отслеживает местоположение.)

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

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