职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 638|回复: 9

装饰器模式和代理模式的区别

[复制链接]
hxy 发表于 2011-8-27 10:11 | 显示全部楼层 |阅读模式
在典型的例子上,两者是非常好区分的。如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如果检测到有敏感关键词,就直接返回空结果了,不会再调用其他检索类了,所以不是
装饰类,而是代理类。

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

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


大小: 9.2 KB
查看图片附件

broken 发表于 2011-8-27 10:11 | 显示全部楼层
分清模式的名称没那么重要,只要使用时“应景”就行了。
代理的使用者一般不会关心被代理的对象的存在的,通常构造Proxy的时候,不用把被代理的对象传给它。Decorator正好相反,使用者需要清楚要装饰的是什么东西,Java IO包里的很多类就是装饰者。
这两者其实使用时是很难混淆的,只是很多人搞不清楚这个类的命名应该是Proxy还是Decorator而已,但是从结构和功能上,其实都不会用错的。

会玩就好 发表于 2011-8-27 10:11 | 显示全部楼层
恩,加深下理解,面试有可能会问!

不过只要答控制访问和新增行为就可以了!

应该不会追问,什么是控制访问,什么是新增行为



已经来了吗 发表于 2011-8-27 10:11 | 显示全部楼层
http4j 写道
代理的使用者一般不会关心被代理的对象的存在的


这句话说反了吧。应该是 代理的使用者一般不会关心代理对象的存在。

目标对象是否被代理了,对于使用者而言是透明的。使用者感觉不到代理对象的存在。
而不是感觉不到被代理对象的存在。





fl 发表于 2011-8-27 10:11 | 显示全部楼层
sswh 写道
http4j 写道
代理的使用者一般不会关心被代理的对象的存在的


这句话说反了吧。应该是 代理的使用者一般不会关心代理对象的存在。

使用者感觉不到代理对象的存在。
而不是感觉不到被代理对象的存在。







在远程代理和控制访问中,客户端应该直接访问代理者,而不是被代理者。


能文能武 发表于 2011-8-27 10:11 | 显示全部楼层
xu_zh_h 写道

在远程代理和控制访问中,客户端应该直接访问代理者,而不是被代理者。



"目标对象是否被代理了,对于使用者而言是透明的。"
弄清楚这句话是什么意思吧。


曾经的小孩 发表于 2011-8-27 10:12 | 显示全部楼层
sswh 写道
xu_zh_h 写道

在远程代理和控制访问中,客户端应该直接访问代理者,而不是被代理者。



"目标对象是否被代理了,对于使用者而言是透明的。"
弄清楚这句话是什么意思吧。



你这是用Spring一类的框架产生的错觉罢了。



jinchang 发表于 2011-8-27 10:12 | 显示全部楼层
感觉作者专门侧重定于这些表面内容了。


代理模式:比如你就是代理,那你就该执行你代理角色的

职能。我们可以在执行角色职能先后,可以按自己想法去做,比如dobefore,doafter。

装饰模式:不要你去代理,而是你去装饰。让你去保持类的本来职责的同时,动态增加新的变化。

装饰设计与代理设计完全不一样,可能从字面我们可以发现其实可以替换的,但意义完全不一样了。我们不是过程化,要OO思想,所以一些场景包括设计思想要考虑,不要考虑用另外一种模式也可以完成一样看起来差别不大的功能。

无错不是错,这话不正确。


为什么AOP用到代理,因为简单,作者设计意图就是用代理处理的。其它模式能处理,代理更具00思想。


为什么老大找你做代理,而不去自己加强自己技能的提高呢?为什么公司有了总裁,还需要职业经理人呢?

(装饰)自己去实现,导致职责过多,势必会影响其它类的职责,削弱或者抑制其它类的完成职责作用,当变化发生,设计遭受意想不到的破坏。

      一般职责过多,在系统中频繁使用,很容易导致职责越弄越大,甚至改不动了







jinchang 发表于 2011-8-27 10:12 | 显示全部楼层
装饰模式是在原有基础之上增加额外的功能,而代理模式有两种情况可以使用第一种是延迟代理对象,对于大文件或者目前还未加载完的对象,使用比较合适。第二种为权限判断,在调用功能前判断当前用户是否有此权限。

broken 发表于 2011-8-27 10:12 | 显示全部楼层
虽然结构大致一样,其实两个模式很好分的。
装饰者:为了解决新增某个功能,引起类剧增的问题,客户端一般都是直接用具体了编程
代理模式:主要就是为了代理,主要是面向接口的,客户端一般直接用接口编程

您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-4-29 16:14 , Processed in 0.142012 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表