1. 程式人生 > >再議:裝飾器模式和代理模式的區別

再議:裝飾器模式和代理模式的區別

在典型的例子上,兩者是非常好區分的。如spring的AOP、遠端代理類、JDK的proxy,都是代理模式。JDK裡的輸入/輸出器是很典型的裝飾器模式! 
但在有些場景上,對設計模式入門的新手,還是有點難區分,我曾經也一度為此困惑。 
兩個模式的UML類圖基本沒區別,都是實現同一個介面,一個類包裝另一個類。 

兩者的定義 
裝飾器模式:能動態的新增或組合物件的行為。 
代理模式:為其他物件提供一種代理以控制對這個物件的訪問. 
裝飾模式是“新增行為”,而代理模式是“控制訪問”。關鍵就是我們如何判斷是“新增行為”還是“控制訪問”。 

來看一個例子 
之前設計的搜尋引擎檢索模組: 



Searcher:檢索類介面 
IllegalKeywordFilterSearcher:非法關鍵詞過濾檢索類,即如果搜尋關鍵詞裡包含非法關鍵詞,直接返回空結果集。 

CachedSearcher:快取檢索類,相同檢索條件快取已經有資料,返回快取裡的結果集。 
DistributedSearcher:分散式檢索類,呼叫多臺伺服器的檢索服務,然後合併最終的結果集。 
LocalSearcher:本地檢索類,只能從當臺伺服器上檢索結果 
HightLightSearcher:高亮檢索類,操作結果集,找到跟搜尋條件最相關的片段,並且關鍵詞上高亮。 

其中HightLightSearcher很明顯是裝飾類,新增了高亮的行為。 
CachedSearcher是代理類,可能也沒疑義,因為可能聽說過“快取代理”的說法。 

IllegalKeywordFilterSearcher就不好確定是代理類還是裝飾類,可以理解是控制訪問,也可以理解成是新增行為,畢竟它是業務需求,總覺得業務需求應該屬於行為。 


看了這篇文章之後difference-between-decorator-and-proxy-patterns就非常明確了。 

原句:I think we’re all aware that the decorator pattern is used to add behavior to existing code. This does not stop at one kind of behavior but any number of different things that we want to do. 
意譯:裝飾類只能新增行為,不能跳過其他的任何一個行為。 

IllegalKeywordFilterSearcher如果檢測到有敏感關鍵詞,就直接返回空結果了,不會再呼叫其他檢索類了,所以不是 

裝飾類,而是代理類。 

當然,有些類可能既有控制訪問的邏輯,也有新增行為邏輯。比如高亮和快取整合在一個類裡,但是違反了單一職責原則,覺得也沒討論的必要。 

網上已經有很多關於兩者區別的文章,但是評判的標準的都不是非常明確,我不知道大家有沒有類似的困惑。