2013-01-06 172 views
15

我正在閱讀由埃裏克埃文斯寫的輝煌的書籍「域驅動設計」。 Eric在他的書中描述了兩個不同的概念:規範模式和策略。規範和政策之間的區別?

這裏是一個規範的例子:

public interface ProjectSpecification { 
    public boolean isSatisfiedBy(Project p); 
} 

public class ProjectIsOverdueSpecification implements ProjectSpecification { 
    public boolean isSatisfiedBy(Project p) { … } 
} 

//client: 
if { 
    (projectIsOverdueSpecification.isSatisfiedBy(theCurrentProject) { … } 
} 

這裏是一個政策的一個例子:

public class CargoBooking { 

    private OverBookingPolicy overBookingPolicy = new OverBookingPolicy(); 

    public int makeBooking(Cargo cargo, Voyage voyage) { 
    if (!overbookingPolicy.isAllowed(cargo, voyage)) 
     return –1; 
    int confirmation = orderConfirmationSequence.next(); 
    voyage.addCargo(cargo, confirmation); 
    return confirmation; 
    } 
} 

public OverBookingPolicy { 
    public boolean isAllowed(Cargo cargo, Voyage voyage) { 
    return (cargo.size() + voyage.bookedCargoSize()) <= (voyage.capacity() * 1.1); 
    } 
} 

我知道,一個政策實際上是一種策略,但上面有兩個例子是絕對沒有區別的。所以我現在的問題是:這兩種模式有什麼區別?這兩種模式都使業務規則明確,所以爲什麼我們要區分這兩種模式?對我而言,這兩者都是一種謂詞。

+0

我會說,規範的目標是描述實例和策略的功能是關於描述操作。但我真的不確定,但我也讀過這本書。 – SpaceTrucker

回答

31

後面說明書中的主要思想是,它是一個謂詞,這通常意味着使用邏輯運算符與它

SPECIFICATION是既定的形式主義的適配(Eric Evans的DDD,第274頁)

例如

例如我們可以說盒子是紅色的,即滿足一些RedSpecification。我們可以聲明一些GreenSpecification,甚至是一個複合的RedOrGreenSpecification。 如果我們有一個支持邏輯操作的規範一些先進的架構也可以是像

BoxSpecification redBoxSpec = BoxSpecification.forColor(BoxColor.RED); 
BoxSpecification greenBoxSpec = BoxSpecification.forColor(BoxColor.GREEN); 
BoxSpecification redOrGreenBoxSpec = redBoxSpec.or(greenBoxSpec); 

那麼我們就可以使用該規範例如從一些資料庫查詢所有紅/綠框:

Collection<Box> boxes = boxRepository.findAll(redOrGreenBoxSpec); 

至於POLICY - 它是STRATEGY模式的變體,但其主要目的是封裝業務規則是一些聲明性表單。

技術上 - 它並不總是直接執行戰略 - 在第一階段,也可以只是一個單獨的類(因爲它在藍皮書的第一分會所示),但以後就可以很容易地擴展

政策是被稱爲策略的設計模式的另一個名稱它通常是出於需要替代不同規則的動機,這在我們所知的情況下並不需要。但是,我們正試圖捕獲的概念不適合政策的意義,這是在領域驅動設計

例如我們包在黃色箱子禮物在1月份同樣重要的動機,並以紅色箱二月

public class Box{ 
    public BoxColor getColor(){} 
    public void recolor(BoxColor color){} 
} 

public class BoxFactory{ 
    public Box createDefaultBox(SomeDate date){ 
     NewBoxPolicy boxPolicy = PolicyRegistry.getNewBoxPolicyForDate(date); 
     Box box = new Box(); 
     boxPolicy.prepareBox(box); 
     return box; 
    } 
} 
public interface NewBoxPolicy{ 
    void prepareBox(Box box); 
} 
public class FebruaryNewBoxPolicy implements NewBoxPolicy{ 
    public void prepareBox(Box box) { box.recolor(BoxColor.RED}; } 
} 
public class JanuaryNewBoxPolicy implements NewBoxPolicy{ 
    public void prepareBox(Box box) { box.recolor(BoxColor.YELLOW}; } 
} 
public class PolicyRegistry{ 
    public static NewBoxPolicy getNewBoxPolicyForDate(SomeDate date){ 
     switch (date.month()){ 
     case SomeMonth.JANUARY: return JANUARY_NEW_BOX_POLICY; 
     case SomeMonth.FEBRUARY: return FEBRUARY_NEW_BOX_POLICY; 
     default: throw new AssertionError(); 
     } 
} 

理解這一政策可以封裝的行爲,同時規範只描述了一個對象的屬性(這些屬性可以既滿足或不滿足業務需求)是很重要的。當然,某些驗證策略可以使用SPECIFICATIONs來檢查滿足要求。

因此,您可以在項目中擁有許多不同的SPECIFICATION實例,並且可以從業務角度描述有效和無效對象。實際上,規範根本沒有意義:例如,如果您有產品搜索站點,則用戶可以指定一個請求來搜索名爲「XBOX」的產品,但是供應商名稱爲「Sony」,如果知道只有特定的供應商可以生產特定的產品,而不是捕獲到您的模型中。

POLICY的重要方面是它的意圖是封裝實際的業務規則(所以代碼不分散在項目的不同部分),所以當規則改變時你可以很容易地找到相應的類。所以你可以在你的項目中有許多規格說明,但是有一定數量的政策,這些政策應該很容易找到和改變。

P.S.請注意,這篇文章僅僅是一個例子,而不是過度工程的許可證,當然你應該儘可能使用最簡單的設計,這是一個常識問題。

+0

很好,綜合答案! – eulerfx

+0

讓我明白這一點。策略包含算法。規格是謂詞,因此僅限於布爾檢查。我有這個權利嗎? (說得簡單) – MUG4N

+0

@ MUG4N是 - 這是它們之間的區別,但是SPECIFICATION的最酷特性是組合,而POLICY的特性是包含業務規則的代碼不是分散的(封裝)。沒關係在各地都有很多規格(以及它們的組合)是可以的,但是如果沒有一些集中的地方可以找到它們,那麼有很多政策是不正確的。 –