Каков наилучший способ рефакторинга метода, который имеет слишком много (6+) параметров? - PullRequest
86 голосов
/ 13 января 2009

Время от времени я сталкиваюсь с методами с неудобным количеством параметров. Чаще всего они кажутся конструкторами. Кажется, должен быть лучший путь, но я не вижу, что это.

return new Shniz(foo, bar, baz, quux, fred, wilma, barney, dino, donkey)

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

ShnizArgs args = new ShnizArgs(foo, bar, baz, quux, fred, wilma, barney, dino, donkey)
return new Shniz(args);

Так что это не похоже на улучшение. Так каков наилучший подход?

Ответы [ 23 ]

0 голосов
/ 13 января 2009

Одним из соображений является то, какое из значений будет доступно только для чтения после создания объекта?

Публично доступные для записи свойства могут быть назначены после создания.

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

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

Было бы очень странно иметь объект, требующий 7 или более параметров, чтобы придать объекту полное состояние и все по-настоящему внешне по своей природе.

0 голосов
/ 13 января 2009

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

В некоторых случаях 7-параметрический конструктор может указывать на плохую иерархию классов: в этом случае предложенная выше структура / класс помощника обычно является хорошим подходом, но тогда вы также склонны в конечном итоге получить множество структур, просто мешки с недвижимостью и ничего полезного. Конструктор с 8 аргументами может также указывать на то, что ваш класс слишком универсален / слишком универсален, поэтому для его практического применения необходимо множество параметров. В этом случае вы можете либо реорганизовать класс, либо реализовать статические конструкторы, которые скрывают реальные сложные конструкторы: например. Shniz.NewBaz (foo, bar) может фактически вызывать реальный конструктор, передавая правильные параметры.

0 голосов
/ 13 января 2009

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

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

См. Ниже:

public class Toto {
    private final String state0;
    private final String state1;
    private final String state2;
    private final String state3;

    public Toto(String arg0, String arg1, String arg2, String arg3) {
        this.state0 = arg0;
        this.state1 = arg1;
        this.state2 = arg2;
        this.state3 = arg3;
    }

    public static class TotoBuilder {
        private String arg0;
        private String arg1;
        private String arg2;
        private String arg3;

        public TotoBuilder addArg0(String arg) {
            this.arg0 = arg;
            return this;
        }
        public TotoBuilder addArg1(String arg) {
            this.arg1 = arg;
            return this;
        }
        public TotoBuilder addArg2(String arg) {
            this.arg2 = arg;
            return this;
        }
        public TotoBuilder addArg3(String arg) {
            this.arg3 = arg;
            return this;
        }

        public Toto newInstance() {
            // maybe add some validation ...
            return new Toto(this.arg0, this.arg1, this.arg2, this.arg3);
        }
    }

    public static void main(String[] args) {
        Toto toto = new TotoBuilder()
            .addArg0("0")
            .addArg1("1")
            .addArg2("2")
            .addArg3("3")
            .newInstance();
    }

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