在NHibernate中映射装饰器模式

时间:2011-07-17 11:13:06

标签: nhibernate design-patterns architecture domain-driven-design decorator

继续这个问题:

Composition over Inheritance - where do extra properties go?

接受的答案和类似答案很好地回答了这个问题。但要进一步说明,如果销售部门和生产部门希望记录有关疾病和假期缺勤的不同信息,该怎么办?这可能是一个解决方案:

public class Holiday : Absence
{
    //Extra fields go here.
}

public class Sickness : Absence
{
    //Extra fields go here.
}

public class SalesHoliday : Holiday
{
    //Extra fields go here.
}

public class SalesSickness : Sickness
{
    //Extra fields go here.
}

public class ProductionHoliday : Sickness
{
    //Extra fields go here.
}

public class ProductionSickness : Sickness
{
    //Extra fields go here.
}
显然,这是阶级爆炸的开始,只会变得更糟,因此应该避免。

一种可能的解决方案是使用Decorator Pattern(Gang of Four)。这将是理想的,但在这个假设的例子中,持久性是使用NHibernate。我已经到处寻找一个如何在NHibernate中映射Decorator模式而没有找到任何东西的例子。我的实验有一点,利用了子类映射,连接子类映射,并集子类映射,鉴别符,隐式多态和多对映射的各种组合,但到目前为止还没有令人满意的结果。有没有人破解过这个? Employee实体将拥有任何类型的缺席集合,因此需要多态行为。

2 个答案:

答案 0 :(得分:3)

在对这种特定类型的应用程序进行建模时,我会尝试远离基于部门的缺勤分类。相反,我会尝试使缺席处理系统能够支持任何部门。您可以设计一个模型,允许在必要时向缺席添加自定义属性。这可以使用通用注释字段或字典来完成。然后,这些数据可以通过给定的上下文进一步构建,例如销售和生产。

考虑到这一点的一种方法是,销售部门的缺席很像生产部门的缺席,因此实体的“类型”不会改变。可能改变的是关于缺席的特定细节,这反过来又保证了构成优于继承方法。

答案 1 :(得分:0)

我终于回答了我自己的问题。 Union-subclass是前进的方式,就像在这个披萨示例中一样:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Decorator.Domain.Entities"
                   assembly="Decorator.Domain">
  <class name="IPizza" abstract="true">
    <id name="Id" column="Id" type="guid">
      <generator class="assigned"/>
    </id>
    <many-to-one name="Order" class="Order" column="`OrderId`" cascade="save-update" />

    <union-subclass name="Pizza" table ="`Pizza`" >
      <property name="Size" column="`Size`" />
      <property name="Cheese" />
      <property name="Tomato" />
    </union-subclass>

    <union-subclass name="PepperoniDecorator" table ="`PepperoniDecorator`" >
      <many-to-one name="BasePizza" class="IPizza" column="`BasePizzaId`" cascade="all" />
      <property name="ExtraSpicy" column="`ExtraSpicy`" />
    </union-subclass>

    <union-subclass name="OliveDecorator" table ="`OliveDecorator`" >
      <many-to-one name="BasePizza" class="IPizza" column="`BasePizzaId`" cascade="all" />
      <property name="Colour" column="`Colour`" />
    </union-subclass>
  </class>
</hibernate-mapping>

我在博客上详细介绍了这一点:

http://lucidcoding.blogspot.co.uk/2013/07/mapping-decorator-pattern-in-nhibernate.html