裝飾模式
理想的裝飾模式的UML圖如下:

dp-decorator.png
理想的裝飾器模式要求對客戶端透明,只改變行為,不改變接口。
Hamcrest中的裝飾模式
在Hamcrest中,為了表達更為復雜的Matcher邏輯,或者增強可讀性,框架提供了類似Is\IsNot\Allof\AnyOf等裝飾器, 實現(xiàn)了對于原有被裝飾對象的功能增強,屬于一種簡化的裝飾模式。
IsNot: NOT
AllOf:AND
AnyOf: OR
assertThat(cheese, is(equalTo(smelly)))
assertThat(cheese, is(not(equalTo(smelly))))
assertThat("myValue", allOf(startsWith("my"), containsString("Val")))
assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))
Matcher是hamcrest框架的核心,其的主要功能是傳入一個類實例,以判斷該實例是否能和當前Matcher所定義的邏輯匹配。BaseMatcher實現(xiàn)了接口Matcher,而其下的Matcher,如IsAnything、IsEqual、IsSame、IsNull等都是ConcreteComponent。右側的Matcher,如Is、IsNot、AnyOf、AllOf)都是Decorator。

Matcher 類圖(部分)
從上述案例,也可以看到Decorator Matcher可以套接其他的Decorator Matcher,如is(not(XXXMatcher)),用于表達更為復雜的邏輯,而每個類也可以只關注自己的邏輯,而把其他邏輯交給其他Matcher,保證了各自實現(xiàn)的原子性。
以下內容摘自Hamcrest的JavaDoc
public boolean matches(java.lang.Object arg)
Description copied from interface: Matcher
Evaluates the matcher for argument item.
This method matches against Object, instead of the generic type T. This is because the caller of the Matcher does not know at runtime what the type is (because of type erasure with Java generics). It is down to the implementations to check the correct type.
Parameters:
arg - the object against which the matcher is evaluated.
Returns:
true if item matches, otherwise false.
Is 類
Is類是個Matcher的裝飾器,但這個Matcher沒有提供更多的行為,它只是在描述前加入“is ”字符串,從而是錯誤信息的描述信息更加符合閱讀習慣。
public static <T> Matcher<T> is(Matcher<T> matcher)
Decorates another Matcher, retaining its behaviour, but allowing tests to be slightly more expressive.
For example:
assertThat(cheese, is(equalTo(smelly)))
instead of:
assertThat(cheese, equalTo(smelly))
IsNot類
IsNot這個Matcher提供“非邏輯”,并在描述前加”not “字符串。
public static <T> Matcher<T> not(Matcher<T> matcher)
Creates a matcher that wraps an existing matcher, but inverts the logic by which it will match.
For example:
assertThat(cheese, is(not(equalTo(smelly))))
Parameters:
matcher - the matcher whose sense should be inverted
AnyOf
public static <T> AnyOf<T> anyOf(Matcher<T> first,
Matcher<? super T> second)
Creates a matcher that matches if the examined object matches ANY of the specified matchers.
For example:
assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))