I prefer application level factories.
If you store Factories at the domain level, they will not help you when you need complex types as parameters (example C # code):
Application Layer: //this Factory resides in the Domain Layer and cannot reference anything else outside it Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate( string name, string code, string streetName,... and lots of other parameters...); //these ones reside in Application Layer, thus can be much more simple and readable: Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(CreatePersonCommand); Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(PersonDTO); Domain Layer: public class Person : Entity<Person> { public Address Address {get;private set;} public Account Account {get;private set;} public Contact Contact {get;private set;} public string Name {get;private set;} public Person(string name, Address address,Account account, Contact contact) { //some validations & assigning values... this.Address = address; //and so on... } } public class Address:Entity<Address>{ public string Code {get;private set;} public string StreetName {get;private set;} public int Number {get;private set;} public string Complement {get;private set;} public Address(string code, string streetName, int number, string complement?) { //some validations & assigning values... code = code; } } public class Account:Entity<Account>{ public int Number {get;private set;} public Account(int number) { //some validations & assigning values... this.Number = number; } } //yout get the idea: //public class Contact...
In addition, there are no obligations to maintain factories within the domain level ( " Domain -driven Development" :
Therefore, shift the responsibility for creating instances of complex objects and Units to a separate object, which may itself be not responsible in the domain model , but is still part of the domain design . Provide an interface that encapsulates all complex assemblies, and this does not require the client to reference specific classes of created objects. Create the whole Set as a unit providing their invariants.
Since I do not use Factories to load stored objects into memory, they should not be accessible from layers other than the Application. Here's why (from a quickly managed domain ):
Another observation is that Factories must create new objects from scratch, or they are necessary to restore objects that previously existed, but probably a database. Returning objects back to memory from their resting place in the database involves a completely different process than creating a new one . One of the obvious differences is that the new entity does not require a new identity card. The object already has one. Violations of invariants are treated differently. When a new object is created from scratch, any violation of invariants ends in an exception. We cannot do this with objects recreated from the database. Objects must be somehow repaired, so they can be functional, otherwise data loss.