再议:装饰器模式和代理模式的区别

来源:互联网 发布:网络福建师范大学校长 编辑:程序博客网 时间:2024/05/29 16:15
在典型的例子上,两者是非常好区分的。如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如果检测到有敏感关键词,就直接返回空结果了,不会再调用其他检索类了,所以不是 
装饰类,而是代理类。 

当然,有些类可能既有控制访问的逻辑,也有新增行为逻辑。比如高亮和缓存整合在一个类里,但是违反了单一职责原则,觉得也没讨论的必要。 

网上已经有很多关于两者区别的文章,但是评判的标准的都不是非常明确,我不知道大家有没有类似的困惑。 
0 0
原创粉丝点击