2016-11-04 2 views
4

У меня есть класс следующим образом:управляющий класс с большим количеством полей

public class Foo { 
    private double A; 
    private double B; 
    ... 
    private double K; 
} 

Он должен содержать 11 плотно связанные параметры, A-K, которая описывает движение точки в земной орбите (своего рода координаты). Я имею в виду, что они не могут быть разделены на подклассы или другие значимые части, поскольку все они имеют одну и ту же цель и смысл. Все эти параметры должны создаваться вместе внутри конструктора, поэтому другой класс мог бы делать необходимые вычисления с Foo и этими 11 полями. Мне дали комментарий о том, что количество параметров внутри конструктора слишком велико.

Есть ли другой способ инициализировать объект Foo без использования гигантского конструктора, карты рода? Надеюсь, я буду достаточно ясным, если нет, я расскажу подробнее.

+0

Не можете использовать массив вместо того, чтобы параметры из ** АК ** ? –

+0

[Шаблон Builder] (https://en.wikipedia.org/wiki/Builder_pattern)? – bradimus

+0

Учитывая описанную ситуацию, похоже, что конструктор с 11 параметрами является самой подходящей реализацией. Выбор другой реализации (например, списка) из-за общего предупреждения компилятора/анализа противоречит основной причине такого предупреждения. Сторона примечания: 11 точек в пространстве? Это для теории струн? – pathfinderelite

ответ

2

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

Что-то вроде:

public class Foo { 
    private double A; 
    private double B; 
    ... 
    private double K; 

    public Foo(double... coordinates) { 
     if (coordinates == null || coordinates.length != 11) { 
      throw new IllegalArgumentException("Unexpected size of coordinates"); 
     } 
     this.A = coordinates[0]; 
     this.B = coordinates[1]; 
     ... 
     this.K = coordinates[10]; 
    } 
    ... 
} 

Таким образом, вы только один параметр определен в конструкторе, но вы все еще можете обеспечить 11 значения для простоты в следующем:

Foo foo = new Foo(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0); 

И вы все равно можете предоставить его как array от double следующим образом:

Foo foo = new Foo(new double[]{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0}); 
+0

очень полезно, спасибо! к сожалению, самая большая проблема заключается в том, что пользователь загружает файл конфигурации с перемещением параметров, не будет никакого способа узнать, какое значение соответствует конкретному параметру. – borgmater

+0

Ну, действительно, я предполагаю, что вы применяете общее соглашение, например, в 3D, если я предоставляю '{1,2,3}' в качестве координат, я неявно знаю, что 'x = 1',' y = 2' и 'z = 3', это может быть другим способом, но тогда это будет полностью не стандарт. –

+1

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

1

Если вызывающий конструктор необходим, как установить 11 прочно связанный параметр последовательным образом я использовал бы такой конструктор или, может быть, как уже сказал, с Array или List.

Если у вас есть или предполагают проблему с согласованностью этих 11 параметров, я бы предпочел создать Foo s с помощью Factory. Если этот Factory использует конструктор с 11 параметрами или 11 вызовами метода набора зависит от вас и ваших пожеланий дизайна этого класса.

Вместо класса Factory вы можете использовать разные конструкторы с другими параметрами и иметь логику для установки 11 параметров в этих разных конструкторах.

1

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

Ответ зависит от конкретных обстоятельств.

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

interface FooData { 
    double getA(); 
    ... 
} 

затем реализовать этот интерфейс над столом или файл конфигурации.

Если объекты создаются «на лету» на основе непосредственного состояния, то некоторая комбинация шаблонов Factory и Builder в порядке.Фабричный шаблон для определения общих наборов значений, если они есть (например, А может быть только 1,0 или 0,0). Builder, чтобы сделать ошибки сложнее.

Во втором случае, за фабрикой и строителем, объект все равно будет иметь конструктор 11-аргументов, просто скрытый от внешнего мира.

0

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

public class AValue { 
    public final double val; 
    public AValue(double val) { this.val = val; } 
} 

, а затем, некрасиво, но (может быть?) Полезно: скопировать, что более 10 раз, чтобы в конечном итоге с 11-х классов для Avalue до-значение.

Тогда вы можете положить вниз ваш конструктор, как

public Foo(AValue a, BValue b, ... and so on) { 

Это позволяет чистой, компилятор поддерживается интерфейс для создания Foo.

И это не значит, что Foo должен хранить 11 объектов; он может просто вставить их в какой-то двойной массив, который имеет 11 слотов. Конечно, вы можете также добавить типа безопасные методы как

AValue getA() 

для вашего класса Foo.

И кроме того, вы можете даже обратиться к Николя ответ и на это:

interface ValueType { public double getValue(); } 
class AValue implements ValueType { 
    ... 
    @Override 
    double getValue() { return value; } 

с

public class Foo { 

    public Foo(AValue a, BValue b, ... KValue k) { 
    this((ValueType) a, ..., (ValueType) k); 
    } 
    Foo(ValueType... values) { 
    ... push values into double[] 
Смежные вопросы