Считается ли плохим дизайном делать длинные операции в конструкторе? - PullRequest
8 голосов
/ 06 ноября 2008

Я реализую класс для сравнения деревьев каталогов (в C #). Сначала я реализовал фактическое сравнение в конструкторе класса. Как это:

DirectoryComparer c = new DirectoryComparer("C:\\Dir1", "C:\\Dir2");

Но нехорошо делать возможную длительную операцию в конструкторе. Альтернативный способ - сделать конструктор закрытым и добавить статический метод, подобный этому:

DirectoryComparer c = DirectoryComparer.Compare("C:\\Dir1", "C:\\Dir2");

Что ты думаешь? Вы ожидаете, что конструктор будет "быстрым"? Второй пример лучше или просто усложняет использование класса?

Кстати:

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

Edit:

Просто чтобы немного пояснить мой пример. Я не только заинтересован, если каталоги отличаются, меня также интересует, как они различаются (какие файлы). Так что простого возвращаемого значения int будет недостаточно. Ответ от cdragon76.myopenid.com на самом деле очень близок к тому, что я хочу (+1 к вам).

Ответы [ 14 ]

0 голосов
/ 07 ноября 2008

Я бы точно сделал второе.

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

Теперь я вижу, что люди делают в конструкторах вызов виртуальных методов. Это ПЛОХО, поскольку, когда кто-то использует вас в качестве базового класса и переопределяет одну из этих функций, вы вызовете версию базового класса, а не производный класс, как только попадете в конструктор.

0 голосов
/ 07 ноября 2008

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

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

Ни в том, ни в другом случае конструктор не выполняет никакой работы, кроме инициализации экземпляра. В приведенном выше случае алгоритм управляется клиентом, как, например, итератор, или потоком прослушивания событий.

Я обычно стараюсь делать такие вещи: Не храните состояние в экземпляре, если оно может быть передано в качестве аргументов сервисным методам. Попробуйте спроектировать объект с неизменным состоянием. Определение атрибутов, таких как те, которые используются в equals и hashcode, всегда должно быть неизменным.

Концептуально конструктор - это функция, отображающая представление объекта на объект, который он представляет.

По приведенному выше определению Integer.valueOf (1) на самом деле является скорее конструктором, чем новым Integer (1), потому что Integer.valueOf (1) == Integer.valueOf (1). , В любом случае это понятие также означает, что все аргументы cosntructor и только аргумент конструктора должны определять поведение объекта equals.

0 голосов
/ 06 ноября 2008

Если операция может занять неизвестное количество времени, это операция, которую вы, возможно, захотите экспортировать в другой поток (чтобы ваш основной поток не блокировался и мог выполнять другие действия, такие как, например, отображение индикатора прогресса вращения). ). Другие приложения могут не захотеть этого делать, они могут захотеть все внутри одного потока (например, те, которые не имеют пользовательского интерфейса). Перемещение создания объекта в отдельный поток немного неудобно, ИМХО. Я предпочел бы создать объект (быстро) в моем текущем потоке, а затем просто позволить его методу запускаться в другом потоке, и как только метод завершит работу, другой поток может умереть, и я могу получить результат этого метода в своем текущий поток, используя другой метод объекта перед тем, как сбросить объект, так как я рад, как только узнаю результат (или сохраняю копию, если результат включает в себя больше деталей, возможно, мне придется использовать по одному).

0 голосов
/ 06 ноября 2008

Если вы работаете с C #, вы можете использовать методы расширения, чтобы создать метод для сравнения двух каталогов, которые вы присоединяете к сборке в DirectoryClass, так что это будет выглядеть примерно так:

Directory dir1 = new Directory("C:\.....");
Directory dir2 = new Directory("D:\.....");

DirectoryCompare c = dir1.CompareTo(dir2);

Это было бы намного более ясной реализацией. Подробнее о методах расширения здесь .

...