Как убрать круговую зависимость из двух классов, которые являются конкретными типами - PullRequest
2 голосов
/ 30 августа 2011

У меня есть два класса, которые выглядят следующим образом:

public class A{
private String id ;
private SortedMap<String,B> answer = new TreeMap<String,B>();
private String text;
}

public class B{
private String id = null ;
private SortedMap<String,A> question = new TreeMap<String,A>();
private String text = null;
}

Есть ли способ удалить циклическую зависимость из вышеуказанных классов ..?

Ответы [ 8 ]

4 голосов
/ 30 августа 2011

Нет, нет, но это не проблема.

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

Сборщик мусора обнаружит циклические зависимости и прекрасно справится с этим.

Единственные проблемы возникают при наличии круговойзависимости в обоих конструкторах, которые приведут к переполнению стека:)

1 голос
/ 25 октября 2012

(на самом деле это комментарий, но у меня недостаточно очков репутации, чтобы сделать это)

: -> почему вы хотите это сделать?
потому что findbugs говорит об этом в Pattern: CD_CIRCULAR_DEPENDENCY: Этот класс имеет круговую зависимость с другими классами. Это затрудняет построение этих классов, так как каждый зависит от правильного построения. Рассмотрите возможность использования интерфейсов для преодоления жесткой зависимости.

также Википедия говорит: ... в разработке программного обеспечения круговые зависимости между более крупными программными модулями считаются анти-паттерном из-за их негативных последствий ... Круговые зависимости часто вводятся неопытными программистами ...

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

Если у вас есть два класса, которые ссылаются друг на друга, javac разрешит это, если вы скомпилируете оба одновременно:

file: dev/A.java
class A {
    B b = null;
    public A(B b)
    {
        this.b = b;
    }
};

file: dev/B.java
package dev;
class B {
    A a = null;
    public B(A a )
    {
        this.a = a;
    }
};

$ javac -d classes dev/A.java
dev/A.java:3: cannot find symbol
symbol  : class B
location: class dev.A
    B b = null;
^
dev/A.java:4: cannot find symbol
symbol  : class B
location: class dev.A
    public A(B b)
             ^
2 errors
$ javac -d classes dev/B.java
dev/B.java:3: cannot find symbol
symbol  : class A
location: class dev.B
    A a = null;
    ^
dev/B.java:4: cannot find symbol
symbol  : class A
location: class dev.B
    public B(A a ) 
         ^
2 errors`

, но если вы введете:

$ javac -d classes dev/A.java dev/B.java

itразрешит зависимость циклического компилятора.

1 голос
/ 30 августа 2011

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

public class AB {
    private final String id ;
    private final SortedMap<String,AB> answer = new TreeMap<String,AB>();
    private final String text;
    private final boolean isA; // if you need to know if its an A or B.
}
1 голос
/ 30 августа 2011

Нет, если вы не удалите одну из карт.

0 голосов
/ 30 августа 2011

попробуйте что-то вроде:

import java.util.*;
class Question {
    Question(int id, String question) {
        this.id = id;
        this.question = question;
    }
    static void toString(Question question, StringBuffer sb, int indent) {
        for(int i=0;i<indent;i++)
            sb.append('\t');
        sb.append(question.id).append(' ').append(question.question).append('\n');
        for (Map.Entry<Integer, Answer> entry : question.answers.entrySet()) {
            Answer answer = entry.getValue();
            for(int i=0;i<=indent;i++)
                sb.append('\t');
            sb.append(entry.getKey()).append(' ').append(answer.answer).append('\n');
            if (answer.question != null)  {
                toString(answer.question, sb, indent+2);
            }
        }
    }
    public String toString() {
        StringBuffer sb = new StringBuffer();
        toString(this,sb, 0);
        return sb.toString();
    }
    int id;
    String question;
    SortedMap<Integer, Answer> answers = new TreeMap<Integer, Answer>();
}
class Answer {
    Answer(int id, String answer) {
        this.id = id;
        this.answer = answer;
    }
    final int id;
    final String answer;
    Question question; // may be null
}
public class Main {
    public static void main(String[] args) {
        Question q0 = new Question(0, "What are you looking for?");
        Answer a0 = new Answer(0, "table");
        q0.answers.put(a0.id, a0);
        a0.question = new Question(0, "Which color table you want?");
        a0.question.answers.put(0, new Answer(0, "green"));
        System.out.println(q0);
    }
}
0 голосов
/ 30 августа 2011

Возвращаясь к предыдущему вопросу - вы можете изменить схему xml и добавить какой-нибудь тег <nextquestion> к ответам. Тогда эквивалентный XML-документ будет:

<decision>
  <question id="0">
    <questionText>What type is your OS?</questionText>
    <answer id="0">
      <answerText>windows</answerText>
    </answer>
    <answer id="1">
      <answerText>linux</answerText>
    </answer>
    <answer id="2">
      <answerText>mac</answerText>
    </answer>
  </question>
  <question id="1">
    <questionText>What are you looking for?</questionText>
    <answer id="0">
      <answerText>table</answerText>
      <!-- NEW TAG HERE -->
      <nextquestion refid="3" />
    </answer>
    <answer id="1">
      <answerText>chair</answerText>
    </answer>
    <answer id="2">
      <answerText>bed</answerText>
    </answer>
    <answer id="3">
      <answerText>cloth</answerText>
    </answer>
  </question>
  <!-- ALL QUESTIONS ARE CHILDREN OF ROOT WITH UNIQUE ID -->
  <question id="3">
    <questionText>Which color table you want?</questionText>
    <answer id="0">
      <answerText>green</answerText>
    </answer>
    <answer id="1">
      <answerText>black</answerText>
    </answer>
    <answer id="2">
      <answerText>pink</answerText>
    </answer>
  </question>
</decision>

Возможно, вы захотите использовать уникальные идентификаторы и для ответов, или даже повторно использовать модель, если хотите повторно использовать ответы для разных вопросов ( отношение многие ко многим )

А у вас занятия:

public class Question {
  private int id;
  private String text;
  private Set<Answer> answers;
  // ...
}

public class Answer {
  private int id;
  private String text;
  private Question nextQuestion;
}

И конечно существует круговая зависимость, но она абсолютно необходима и унаследовала от реальной области моделей.

0 голосов
/ 30 августа 2011
public class A{
private String id ;
private SortedMap<String,A> answer;
private String text;
}
public class B extends A{
} 

если вы считаете, что вам нужно, или просто используйте логическое поле в A

...