C # Объект строительства вне конструктора - PullRequest
5 голосов
/ 28 сентября 2011

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

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

Мой вопрос:

  1. Можно ли иметь объекты, основанные на каком-либо методе, или свойство, которое вызывается для них, после чего они могут считать их инициализированными?

  2. Является ли какой-то шаблон для ситуаций, когда ваш объект действует как получатель и должен поддерживать несколько интерфейсов, которые его вызывают, и порядок этих вызовов имеет значение? (что-то лучше, чем установка флагов, например ThisWasDone, ThatWasCalled)

Ответы [ 5 ]

9 голосов
/ 28 сентября 2011

Можно ли иметь объекты, основанные на каком-либо методе, или свойство, которое вызывается для них, после чего они могут считать их инициализированными?

Нет. Методы init - это боль, так как нет гарантии, что их вызовут. Простое решение состоит в том, чтобы переключиться на интерфейсы и использовать шаблон фабрики или компоновщика для создания реализации.

@ Марк Симанн написал статью об этом: http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling.aspx

Существует ли какая-то схема для ситуаций, когда ваш объект действует как получатель и должен поддерживать несколько интерфейсов, которые его вызывают, и порядок этих вызовов имеет значение? (что-то лучше, чем установка флагов, например ThisWasDone, ThatWasCalled)

Шаблон строителя.

0 голосов
/ 28 сентября 2011

Во-первых, Factory Method.

public class MyClass
{
    private MyClass()
    {
    }

    public Create()
    {
        return new MyClass();
    }
}

Во-вторых, почему вы не хотите, чтобы другой класс создал для вас объект?(Factory)

public class MyThingFactory
{
    IThing CreateThing(Speed speed)
    {
        if(speed == Speed.Fast)
        {
            return new FastThing();
        }

        return new SlowThing();
    }
}

В-третьих, почему множественные классы имеют побочные эффекты на новых экземплярах вашего класса?Разве у вас нет декларативного контроля над тем, какие другие классы имеют доступ к вашему объекту?

0 голосов
/ 28 сентября 2011

Я не вижу в этом ничего плохого. Это может быть не очень удобно, но вы не можете ВСЕГДА использовать инициализацию в ctor, как если бы вы не могли водить машину под зеленым светом. Это решения, которые вы сделали на основе требований вашего приложения.

  1. Все в порядке. Представьте, например, что вашему объекту нужно читать данные из потока TCP или из файла, который может отсутствовать или быть поврежден. Возьмите исключение из ctorbaad.

  2. Все в порядке. Если вы думаете, например, о каком-то вашем компиляторе языка DSL, он может выглядеть так:

A) найти все глобальные переменные и проверить, удовлетворяет ли сумма выделенных им средств требованиям вашего устройства

B) анализ ошибок

C) проверка на самоциклирование

И так далее ...

Мотыга это помогает.

0 голосов
/ 28 сентября 2011

Ответ (1)

Почему бы и нет? Двигатель нуждается в водителе, потому что он должен ввести ключ для автомобиля, а затем включить питание. Будет ли автомобиль делать такие вещи, как определение текущей скорости, если двигатель остановлен? Или автомобиль покажет оставшееся масло без включения его?

Некоторые цели программирования не смогут инициализировать своих акторов во время создания объекта, и это не потому, что это неправильный способ выполнения вещей , а потому, что это естественный, регулярный и / или семантически мудрый способ представления всего своего поведения.

Ответ (2)

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

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

0 голосов
/ 28 сентября 2011

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

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

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