Создание объекта на основе состояния другого объекта в Java - PullRequest
5 голосов
/ 23 января 2010

Допустим, у вас есть класс под названием Explosion, в котором нет смысла создавать его экземпляр без некоторой информации из другого экземпляра класса. Конструктор не обнародован.

Лучше сделать это так:

// both classes are in the same package  
Explosion e;  
Collision c = new Collision()    
// do some stuff with collision  
e = c.createExplosion()

Или для Explosion лучше иметь статический метод для создания экземпляра, и вы передаете объект Collision в качестве аргумента:

Explosion e  
Collision c = new Collision()    
// do some stuff with collision  
e = Explosion.createExplosion(c)

Когда вы являетесь автором обоих классов.

Ответы [ 7 ]

4 голосов
/ 23 января 2010

Почему конструктор не публичный? Мне кажется разумным, чтобы Explosion имел конструктор, принимающий ссылку Collision в качестве параметра.

Таким образом, вы могли бы иметь:

Explosion e;
Collision c = new Collision();
// do some stuff with collision
e = new Explosion(c);
3 голосов
/ 23 января 2010

Это зависит ... в значительной степени от зависимости.

Если вы считаете Explosion всегда нижним уровнем или равным Collision, тогда выберите гибкость и простоту использования (виртуального) метода экземпляра. Это сохраняет поведение в объектах и ​​уменьшает потребность в геттерах (которые, как правило, являются признаком плохого дизайна). Конечно, у вас все еще есть вызов конструктора Explosion, только теперь он находится в пределах Collision.

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

3 голосов
/ 23 января 2010

Я предпочитаю второй подход, так как он лучше разделяет ответственность между классами. Чтобы ответить на ваш вопрос, спросите себя, кто несет ответственность за создание Взрыва, и действуйте соответственно. Ваш второй подход в основном использует фабричный метод, чтобы скрыть конструктор, но ответственность по-прежнему лежит в классе Explosion, что является хорошим IMO.

Почему конструктор не публичный? Вы можете сделать его видимым, а затем просто передать Collision в качестве параметра конструктора?

1 голос
/ 23 января 2010

Преимущество второго подхода заключается в том, что вам не нужно каждый раз создавать объект Explosion (имеется в виду Effective Java ). Если вы хотите иметь какой-то механизм кэширования (скажем, вы хотите вернуть тот же экземпляр Explosion, основанный на некоторых атрибутах класса Collision), тогда второй подход полезен.

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

1 голос
/ 23 января 2010
  • Эффективная Java (2-я глава) рекомендует использовать статический фабричный метод, т. Е. Ваш второй вариант.
  • В зависимости от параметров из Collision, которые вам нужны при взрыве, может быть лучше передать только те параметры, что не нарушает Закон Деметры
1 голос
/ 23 января 2010

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

Вот почему: Во-первых, столкновение может иметь много последствий: взрывы, повреждения, выигрыши (это игра)? звук и т. д. Вы не хотите перегружать их всех при столкновении.

С другой стороны, взрывы могут произойти по разным причинам (например, оружие), должен ли взрыв явно знать все, что может его вызвать?

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

1 голос
/ 23 января 2010

Я, конечно, предпочитаю второе, потому что это ОО.

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