Подтвердить что ты не робот

Какие методы следует использовать в моем классе DDD factory?

Я пытаюсь понять, что должен сделать мой класс factory в моем проекте DDD. Да, для создания объектов следует использовать factory, но что именно он должен делать. Рассмотрим следующий factory класс:

    public class ProductFactory
    {
        private static IProductRepository _repository;

        public static Product CreateProduct()
        {
            return new Product();
        }

        public static Product CreateProduct()
        {
            //What else would go here?
        }

        public static Product GetProductById(int productId)
        {
            //Should i be making a direct call to the respoitory from here? 
            Greener.Domain.Product.Product p = _repository.GetProductById(productId);
            return p;
        }
    }

Должен ли я делать прямой вызов в репозиторий из factory?

Как мне управлять созданием объекта при извлечении данных из базы данных?

Что мне нужно сделать, чтобы этот класс был полным, какие другие методы у меня есть?

Должен ли я использовать этот класс для создания объекта Product из домена и хранилища справа?

Пожалуйста, помогите!

4b9b3361

Ответ 1

Должен ли я делать прямой звонок хранилище изнутри factory?

Нет, не используйте factory при извлечении материала, используйте factory только при его создании в первый раз.

Как мне управлять созданием объекта при извлечении данных из базы данных?

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

Что мне нужно сделать для этого класса? полный, какие другие методы должны быть есть?

Многие фабрики не являются даже отдельными классами, они просто методы, которые обеспечивают создание объекта. Вы можете свернуть метод factory в другой класс, если вам кажется, что он просто вызовет конструктор без параметров.

Должен ли я использовать этот класс для создания объект продукта из домена и хранилище справа?

Репозиторий предназначен для создания (в смысле создания) существующих объектов, factory - это первый раз, когда вы создаете объект.

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

Объяснение и пример:

Например, в проекте, над которым я работаю, у меня есть базовый класс процессора excel и многие подклассы, реализующие этот базовый класс. Я использую factory, чтобы получить правильный, а затем вызывать методы на нем, не зная, какой подкласс был возвращен. (Примечание: я изменил некоторые имена переменных и потрошил/изменил много кода)

Основной класс процессора:

public abstract class ExcelProcessor
{
      public abstract Result Process(string ExcelFile);
}

Один из подклассов Процессор:

public class CompanyAExcelProcessor : ExcelProcessor
{
     public override Result Process(string ExcelFile)
     {
      //cool stuff
     }
}

Factory:

 public static ExcelProcessor CreateExcelProcessor(int CompanyId, int CurrentUserId)
 {
      CompanyEnum company = GetCompanyEnum(CompanyId);
      switch (company)
      {
           case CompanyEnum.CompanyA:
                return new CompanyAExcelProcessor();
           case CompanyEnum.CompanyB:
                return new CompanyBExcelProcessor();
           case CompanyEnum.CompanyC:
                return new CompanyCExcelProcessor(CurrentUserId);
           //etc...
      }
 }

Использование:

ExcelProcessor processor = CreateExcelProcessor(12, 34);
processor.Process();

Ответ 2

Будьте осторожны, есть две причины для создания нового объекта: Создание и перерегистрация из базы данных.

Первый случай обрабатывается factory. Вы можете предоставить несколько методов для создания объекта на factory. Factory методы должны возвращать действительные объекты, поэтому вы можете передавать параметры этим методам для предоставления требуемой информации.

Метод factory также может выбрать фактический тип для создания экземпляра на основе параметров.

Нельзя смешивать это с регидратированием из базы данных. Такой экземпляр должен принимать значения из datarow и создавать объект с ним. Обычно я называю это построителем данных вместо factory.

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

Ответ 3

Что нужно сделать в вашем методе factory Create - это то, что необходимо, чтобы поместить бренд, шлепающий новый объект в состояние VALID.

Теперь для некоторых объектов это означает, что вы ничего не сделаете, кроме этого:

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

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

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

Ответ 4

Я лично использовал бы factory в двух случаях:

1) Что-то в другом месте определяет тип объектов, возвращаемых этим factory (т.е. он может возвращать объекты в зависимости от обстоятельств. Например, возвратите объект-заглушку при тестировании, верните фактическую реализацию, когда я нет (это очевидно, больше проблемы с инверсией управления/зависимостями - но если вы еще не хотите добавлять контейнеры в свой проект)).

2) У меня довольно сложные объекты, которые имеют контейнеры, зависимости, другие отношения и т.д., и их нужно тщательно строить, чтобы избежать создания нулевых или бессмысленных ссылок. Например, если у меня есть объект "Расписание", мне могут потребоваться некоторые начальные и конечные поля даты - если логика для извлечения, выясняя эту дату, достаточно сложна, я не хочу, чтобы вызывающий класс знал об этом и просто вызывал по умолчанию factory, который создал объект расписания.

Надеюсь, что это поможет.

Ответ 5

В приведенном выше примере я немного неясен в отношении различия между вашим factory и репозиторием. Интересно, не следует ли просто добавлять CreateProduct в качестве метода в репозиторий и использовать DI, чтобы подтолкнуть хранилище к коду, который ему нужен? Если factory ничего не делает и т.д.

Или, если вы просто хотите, чтобы он действовал как глобально зарегистрированный репозиторий, возможно, что-то вроде:

public static IFooRepository Default {get;private set;}
public static void SetRepository(IFooRepository repository) {
    Default = repository;
}

(на мой взгляд, кажется яснее отделить "набор" в этом случае, но вам не обязательно соглашаться)

и использовать вызывающих абонентов var product = YourFactory.Default.CreateProduct(); и т.д.

Ответ 6

@ThinkBeforeCoding - в примере @m4bwav factory получает действительный идентификатор из вспомогательного метода, но он не создает новую запись на уровне сохранения в любом месте. Если, однако, я использую автогенерируемый столбец с идентификатором базы данных в качестве своих идентификаторов, кажется, что factory должен был вызвать в репозиторий для создания первоначального объекта. Можете ли вы прокомментировать, какой метод "правильный"?

Ответ 7

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

У меня есть объект User, который имеет имя пользователя, пароль и адрес электронной почты, все необходимые атрибуты, поэтому у меня есть:

public class User {
    private String username;
    private String password;
    private String email:

    /**
     * @throws IllegalArgumentException if the username is null, the password is null or the
     * email is null.
     */
    public User(final String theUsername, final String thePassword, final String theEmail) {
        Validate.notNull(theUsername);
        Validate.notNull(thePassword);
        Validate.notNull(theEmail);

        this.username = theUsername;
        this.password = thePassword;
        this.email = theEmail;
    }

    // Getters / Setters / equal / hashCode / toString
}

и тогда у меня есть UserBuilder:

public class UserBuilder {
    private String username;
    private String password;
    private String email;

    public UserBuilder withUsername(final String theUsername) {
        Validate.notNull(theUsername);

        this.username = theUsername;

        return this;
    }

    public UserBuilder withPassword(final String thePassword) {
        Validate.notNull(thePassword);

        this.password = thePassword;

        return this;
    }

    public UserBuilder withEmail(final String theEmail) {
        Validate.notNull(theEmail);

        this.email = theEmail;

        return this;
    }

    public User build() {
        User user = new User(this.username, this.password, this.email);

        return user;
    }
}

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

UserBuilder builder = new UserBuilder();

try {
    User user = builder.withUsername("pmviva").withPassword("My Nifty Password").withEmail("[email protected]").build();
} catch (IllegalArgument exception) {
    // Tried to create the user with invalid arguments
}

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

Надеюсь, это поможет

Спасибо Pablo