工厂模式应该在哪里这个住在DDD?(Factory Pattern where should thi

2019-08-03 20:02发布

我现在一直在讨论这一段时间,仍然没有得出一个结论。 虽然大多数的例子我看到在应用层的工厂代码,我倾向于认为它应该是在领域层。 这种情况的原因:有时我初步验证在我的工厂,我想对象的所有创作经历进行。 我想在我的对象的所有实例化使用该代码。 有时,操作需要这感觉不自然传递给构造函数的参数信息。 而一些更不是重要原因。

有没有原因,这是一个不好的做法? 这是否破坏其他模式?

Answer 1:

+1这样做。 辅助功能将是一个很好的理由,我会保持造物代码至少接近域模型层。 否则,领域模型的用户,将会得到根本困惑如何找到限制访问时,构造特殊实例化。 其实一个充分的理由来分隔这将是你有不同的有效方法来创建同样的事情,例如采用抽象工厂时,这是通常的情况下。

如果我不得不分开它,我把它放在如包(在Java中的情况下)至少域模型的同级别始终出货与它例如,沿着

upper
  --> domain
  --> domain_factory


Answer 2:

在DDD一个工厂只是实例工厂模式 ,因此它应该用的地方是很有道理的。 另一个要考虑的原则是信息专家基本上规定的行为应该被分配到最接近信息类模式。 因此,如果你有一些特定领域的规则和逻辑,你想强制执行,将工厂领域层 - 毕竟,在工厂创建域对象。 但是请注意,你可能有其他类型的其他层的工厂。



Answer 3:

从内存中,Eric Evans的书有例子,其中对象工厂是域层的重要一环。

对我来说,它可以完美的在这里找到您的工厂。



Answer 4:

我喜欢在应用层工厂。

如果您保留工厂领域层中,他们不会帮助你,当你需要的复杂类型作为参数(C#代码示例):

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...

此外,对保持领域层内的工厂(从没有义务领域驱动设计快速 ):

因此,移位用于创建复杂的对象和聚集体的实例来单独的对象,其本身可以具有在领域模型中没有责任 ,但仍是域设计的一部分的责任。 提供封装所有复杂的组件并且不要求客户端来引用的对象的具体的类被实例化的接口。 作为一个单位创建整个集合,执行其不变。

由于我不使用工厂以持久化对象加载到内存中,他们没有从不是应用的其它层访问。 这也是为什么(从领域驱动设计快速 ):

另一种看法是,工厂需要从头开始创建新的对象,或者他们需要重建其先前存在的对象,但都被可能保存到数据库中。 在数据库中把实体回内存从他们的安息之所涉及不是创建一个新的完全不同的过程 。 一个明显的区别是,新的对象并不需要一个新的身份。 该对象已有一个。 不变量的违规行为的处理方式不同。 当从头开始创建一个新对象时,不变量的任何违反在一个异常结束。 我们不能做到这一点与从数据库中重建对象。 该对象需要以某种方式修复,这样他们就可以是功能性的,否则有数据丢失。



Answer 5:

如果制造商/工厂只对域类和原语的依赖,将它们放置在领域层,否则将它们放置领域层之外。



文章来源: Factory Pattern where should this live in DDD?