3

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

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

Например, если бы я имел Субъект компьютер, состоящий из процессора и объекта памяти, если фабричный метод принимает форму:

public Computer NewComputer(
    string computerName, 
    int processorCores, 
    int processorClockSpeed, 
    string memoryType, 
    int memoryRam) 
{ 
    ... 
} 

или

public Computer NewComputer(
    string computerName, 
    Processor processor, 
    Memory memory) 
{ 
    ... 
} 

это только вопрос вкуса, или есть какие-то серьезные соображения здесь?

ответ

1

«Агрегатный корень» - это самый верхний узел графа объекта. Все остальные объекты создаются и доступны через этот корневой объект. Другими словами: если вы создаете компоненты класса Computer с помощью внешнего заводского метода, вы больше не можете называть его «aggregate root». Это не значит, что ваш второй пример как-то плох или вонючий или что-то в этом роде, он просто не соответствует концепции «совокупного корня» ...

+0

ли какая-нибудь разница, если процессор и память были объектами значение? – sandy

+0

Да, действительно. Если компьютер является сущностью (будь то агрегированный корень или нет), а процессор и память - это объекты ценности, то экземпляр компьютера _must_ создает их внутренне. «Внедрение» их было бы совершенно бессмысленным, поскольку это было бы не чем иным, как глупой копией-операцией. –

+0

Это была бы более чем глупая операция копирования: это было бы инкапсулирование ответственности за создание объектов где-то в другом месте (например, на заводе или в репозитории). Если у вас есть агрегированный корень «PurchaseOrder», который содержит коллекцию объектов LineItem (среди прочего), что бы выглядел конструктор 'BuyOrder'? –

2

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

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

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

1

Что касается преимуществ использования метода Factory (I я не очень хорошо знаком с правилами Агрегатов и Корней):

  • Я думаю, что процессор и память - это объекты, имеющие определенные типы поведения, которые вы хотите отделить от своего класса компьютеров.
  • Конструктор класса компьютер может быть

    public Computer(string computerName, IProcessor processor, IMemory memory) 
    { 
    } 
    

Ваш компьютерный класс в настоящее время не зависит от конкретной реализации процессора и памяти. Другой класс несет ответственность за использование компьютера с определенной памятью и процессором.

При таком подходе у вас будут преимущества наличия более удобного кода и возможность обновления памяти и процессора без изменения компьютера.

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

  1. http://www.objectmentor.com/resources/articles/inheritanceVsDelegation.pdf
  2. SOLID книгу: http://www.lostechies.com/content/pablo_ebook.aspx