找回密码
 FreeOZ用户注册
查看: 1227|回复: 4
打印 上一主题 下一主题

[论坛技术] Visitor设计模式中的一个设计限制问题,回应hoo的文章

[复制链接]
跳转到指定楼层
1#
发表于 17-5-2009 00:48:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
以GoF的典型设计模式来说,Visitor的设计有一些不合理的地方。
书上也说了这些问题带来的制约。现在说出来大家探讨一下。
最近乱发C++问题,似乎感兴趣的人不多,哈哈哈。

首先是Visitor设计模式的假定:

这个假定,或叫制约来自于“适用性”的第三点:定义对象结构的类很少改变,
但经常需要在此结构上定义新的操作。改变对象结构类需要重定义所有访问者的
接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这
些类中定义这些操作较好。

在效果/优缺点也再次提到这个问题,
3) 增加新的ConcreteElement类很困难 Visitor模式使得难以增加新的
Element的子类。每添加一个新的ConcreteElement都要在Visitor中添
加一个新的抽象操作,并在每一个ConcreteVisitor类中实现相应的操作。
有时....还不如说是一种例外。

在这个问题上,hoo同学之前提出的一个观点:假定原有的代码已经冻结,
但又想开发一些新的功能在上面。这个假设是对的。这个时候Visitor正好能
对应上这种假定。

其实这些制约都来自visitor的一个设计原则上的选择:基于实现,而不是基于接口的编译。
查看Visitor的接口设计,就会发现它提供的每个接口都是针对某个特别的子类。这个设计选择
可能和Visitor模式的设计原型有关:

Visitor的设计原型来自于编译器的功能扩展。以变量访问和赋值语句为例,GoF看到每一个这样的
语言单位都需要差不多一样的功能,但针对不同的语言单位,各自的做法又不一样,从而又形成了
两个不同的进化方向:

1. 语言单位的进化方向
2. 功能细节的进化方向

Bridge的出现也是因为类设计出现了两个进化方向,分别是内部特性和外部实现的分化,这里则是类的
内在结构与加在类上的操作/功能的分化。无论哪一种进化,我觉得选择Visitor的关键在于:

1. 其中一个类结构已经基本稳定下来
2. 用于实现功能的类必须很紧密的关联到目标对象身上

我之前看到Bridge的外形象一座桥,只有最顶的两个类存在依据关系(composite)。而Visitor的依赖则
由上到下的穿插着,甚至到了最后,目标对象结构如果出现大的变动,对Visitor模式的影响是毁灭性的。
想象一下,在窗口程序里如果多加几个小点形成的component是否会让XWindowImpl之类的实现类觉得不便?

然而,无论初衷是怎样,这样的强依赖是不合适的。(类似的强依赖在AbstractFactory里也有)

可能对于GoF来说,Visitor的目标对象结构的确定性是明显的,无需考虑的吧。的确,如果现在就摆着一堆类在
那里,让我来重新包一些花样上去,想到最后可能也就只能把新开发的类和这些现有的类包在一起,而不是想什么
抽象之类。而我觉得有问题,是始终立足于系统刚开始的时候的设计阶段。又或者,我还是被那个visitor的名字
继续误导着。

乱写一通,没有什么想法和结论

[ 本帖最后由 key 于 16-5-2009 23:52 编辑 ]

评分

参与人数 1威望 +20 收起 理由
procoder + 20 谢谢分享!

查看全部评分

回复  

使用道具 举报

2#
发表于 17-5-2009 19:40:56 | 只看该作者
回复  

使用道具 举报

3#
发表于 18-5-2009 11:05:31 | 只看该作者
关于我那个visitor的帖子有一些争论和不同意见,可能看问题的角度不同。不过我觉得可能visitor适用的场合,没有得到很好的理解,如果一个类经常要改动,那么它绝对不应该设计成可供visit,让第三方的visitor去完成应该它做的事情。visitor好比是开了一道后门,也许永远都锁着,但是说不定哪天就用上这道门了(逃跑?),而潜在的那些visitor所做的事情,应该全部是在基于这个类已经提供的功能上,进行扩展。Visitor模式的重点在于偶然的扩展,而不是频繁的修改。

评分

参与人数 1威望 +20 收起 理由
procoder + 20 谢谢分享!

查看全部评分

回复  

使用道具 举报

4#
发表于 19-5-2009 10:08:27 | 只看该作者
其实hoop的场景是有道理的,c# 3.0引进的extension methods使用的就是vistitor的方式,他的场景是.net framework你不能动,因为你连源码都没有,但是你还是可以扩展.net framework的类的methods。

其实模式脱离场景来讨论就没有意义了,在GoF里面已经提出每个模式的优点和缺点,没有万能的模式,否则有经验的设计师不会那么难找和值钱。

评分

参与人数 1威望 +30 收起 理由
coredump + 30 我很赞同!

查看全部评分

回复  

使用道具 举报

5#
发表于 19-5-2009 12:56:15 | 只看该作者

回复 #4 procoder 的帖子

只要visitor对应的场景是相对稳定的即可,visitor这个模式一开始就是应用在编译器语法检查,语法生成,语法映射等场合下,在这种情形下,语法规范被认为是稳定的,而由语法规范visitor生成的衍生功能是异变的。类似情形比如网络协议,框架,正规的商业规范等等都适合visitor模式。

如果想对稳定的那个发生了变化,则所以依赖的visitor需要跟着变也是合情合理的,比如.NET CLR发生了变化,Java语法发生了变化,http协议发生了变化等等。
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+11, 2-11-2024 10:20 , Processed in 0.039845 second(s), 26 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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