2009-03-04 7 views
12

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

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; 
     } 
    } 

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

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

Что мне нужно для завершения этого класса, какие у меня другие методы?

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

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

+1

Не помещайте логики хранилища в вашем заводе. – mbillard

ответ

0

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

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

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

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

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

1

лично я бы использовать завод в нескольких случаях:

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

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

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

2

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

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

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

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

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

11

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

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

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

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

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

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

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

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

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

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

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

Базовый класс процессора:

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

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

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

Фабрика:

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(); 
6

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

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

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

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

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

+3

Завод обычно находится в домене, а сборщик данных находится в инфраструктуре persistent. – thinkbeforecoding

0

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

0

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

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

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 
} 

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

Надеется, что это помогает

Благодаря Пабло

 Смежные вопросы

  • Нет связанных вопросов^_^