我正在使用 DDD 构建一个应用程序,但是我很难理解你应该在哪里实例化规范类或使用它们。
我的应用大量使用预订窗口,因此我有一个规范,可确保即将添加到聚合中的预订窗口不会与当前处于聚合中的另一个窗口重叠。像下面这样。
/// <summary>
/// A specification that determines if the window passed in collides with other windows.
/// </summary>
public class BookingTemplateWindowDoesNotCollideSpecification : ISpecification<BookingScheduleTemplateWindow>
{
/// <summary>
/// The other windows to check the passed in window against.
/// </summary>
private readonly IEnumerable<BookingScheduleTemplateWindow> otherWindows;
/// <summary>
/// Initializes a new instance of the <see cref="BookingTemplateWindowDoesNotCollideSpecification" /> class.
/// </summary>
/// <param name="otherWindows">The other windows.</param>
public BookingTemplateWindowDoesNotCollideSpecification(IEnumerable<BookingScheduleTemplateWindow> otherWindows)
{
this.otherWindows = otherWindows;
}
/// <summary>
/// Determines whether the window passed in collides with other windows held inside this class.
/// </summary>
/// <param name="obj">The obj.</param>
/// <returns>
/// <c>true</c> if [is satisfied by] [the specified obj]; otherwise, <c>false</c>.
/// </returns>
public bool IsSatisfiedBy(BookingScheduleTemplateWindow obj)
{
return !this.otherWindows.Any(w => obj.DayOfWeek == w.DayOfWeek && w.WindowPeriod.IsOverlap(obj.WindowPeriod));
}
}
然后我有一个聚合方法,允许使用规范添加新窗口。已经持久化的聚合窗口被传递到规范构造函数中。
public virtual void AddWindow(DayOfWeek dayOfWeek, int startTime, int endTime)
{
var nonCollidingWindowSpecification = new BookingTemplateWindowDoesNotCollideSpecification(this.Windows);
var bookingWindow = new BookingScheduleTemplateWindow(this){
DayOfWeek = dayOfWeek,
WindowPeriod = new Range<int>(startTime, endTime)
};
if (nonCollidingWindowSpecification.IsSatisfiedBy(bookingWindow))
{
this.Windows.Add(bookingWindow);
}
}
我正在苦苦挣扎的是,我的一部分认为我应该将此规范注入到类中,而不是直接实例化(作为我的应用程序的一般规则,而不仅仅是在这种情况下),因为规范的类型可能需要根据实体的状态而改变。但是从 MVC 层注入规范感觉很脏,就好像我稍后有另一个应用程序接口(如 REST API)然后重复使用哪个规范的逻辑。
您如何确保所使用的规范保持灵活,同时确保有关使用哪个规范的逻辑不会在另一个应用程序界面中重复。
在这种情况下,您是否希望将工厂注入实体并从那里返回规范,从而不允许域逻辑溢出到更高层?还是有更好/更清洁/更简单的方法来做到这一点?