Как инициализировать класс со многими аргументами конструктора? - PullRequest
3 голосов
/ 18 октября 2010

У меня есть класс, который принимает много аргументов для создания.Это своего рода аудиопроцессор, которому нужна частота дискретизации, разрешение выборки, количество каналов и т. Д. Большинство параметров имеют нормальные значения по умолчанию.И большинство из них должны быть установлены только в инициализаторе (конструкторе), потому что нет смысла изменять их впоследствии.Я не хочу создавать гигантский инициализатор со всеми параметрами, потому что (1) он будет огромным, и, по сути, он будет только копировать переданные значения, не делая реальной работы, и (2) пользователь должен будет указать значения для всехпараметры.Какой хороший способ решить эту проблему?

Я пытался написать геттеры и сеттеры для параметров.Это означает, что я не смог создать «настоящий» блок обработки звука в конструкторе, так как значения параметров тогда не известны.Мне пришлось ввести новый метод (скажем, prepareForWork), чтобы пользователи могли делать что-то вроде:

AudioProcessor *box = [[AudioProcessor alloc] init];
[box setSampleRate:…];
[box setNumberOfChannels:…];
[box prepareForWork];
[box doSomeProcessing];

Это хорошо, потому что не требует громоздкого конструктора.Также в инициализаторе установлены значения по умолчанию, что означает, что я могу взять новый экземпляр AudioProcessor, и он все еще может выполнить некоторую работу.Обратная сторона в том, что (1) существует дополнительный метод, который необходимо вызвать, прежде чем экземпляр сможет выполнить какую-либо реальную работу, и (2) класс должен отказаться от изменения любого из параметров после вызова prepareForWork.Защита обоих этих инвариантов потребует некоторого стандартного кода, который мне не нравится.

Я думал, что смогу создать специальный «предустановленный» класс, который будет выглядеть следующим образом:

@interface SoundConfig : NSObject {
    NSUInteger numberOfChannels;
    NSUInteger sampleResolution;
    float sampleRate;
}

И затемтребуется экземпляр этого класса в инициализаторе AudioProcessor:

@interface AudioProcessor : NSObject {…}
- (id) initWithConfig: (SoundConfig*) config;

Значения по умолчанию будут установлены в инициализаторе SoundConfig, конструктор AudioProcessor будет простым и не будет сохраняться никаких инвариантовсмотреть вручную.

Еще один подход, о котором я подумал, был своего рода AudioProcessorBuilder класс.Вы должны создать экземпляр этого, установить аудиопараметры с помощью аксессоров, а затем, наконец, он создаст для вас экземпляр AudioProcessor, установив все свойства с помощью закрытых сеттеров, чтобы вы не могли изменить их позже (и нарушилинвариант).

Теперь, когда я пишу это, я предпочитаю подход SoundConfig.Как вы решаете это, есть ли лучший подход?

Ответы [ 3 ]

4 голосов
/ 18 октября 2010

Посмотрите, как реализовано NSURLConnection и использовано .Для параметризации он использует объект NSURLRequest, аналогично тому, как объект SoundConfig параметризует объект AudioProcessor.

2 голосов
/ 18 октября 2010

Обычный способ действительно заключается в создании гигантского инициализатора вместе с несколькими инициализаторами для значений по умолчанию или наборов значений.

-initWithSampleRate:numberOfChannels:sampleResolution:
-initWithSampleRate:sampleResolution:
-initWithSampleRate:numberOfChannels:
-initWithNumberOfChannels:sampleResolution:
-initWithNumberOfChannels:
-initWithSampleResolution:
-initWithSampleRate:
-init

Но подход SoundConfig выглядит проще.

1 голос
/ 18 октября 2010

Обычно, когда у вас есть класс со многими параметрами конструктора, особенно когда некоторые или большинство из них являются необязательными, вы хотите использовать Шаблон построителя . Забавно, я не могу найти примеры для target-c, поэтому я не уверен, что это можно легко применить здесь ...

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