《设计模式沉思录》—第2章2.5节关于VISITOR的一些警告

2.5 关于VISITOR的一些警告
在使用VISITOR模式之前,有两件事情需要考虑。

首先问一下自己,被访问的类层次结构是否稳定?拿我们的例子来说,我们是否会经常定义新的Node子类,还是说这种情况很少见?增加一种新的Node类型可能会迫使我们仅仅为了增加一个相应的visit操作而修改Visitor类层次结构中所有的类。

如果所有的visitor对新的子类不感兴趣,而且我们已经定义了一个与visitNode等价的操作来在默认情况下进行合理的处理,那么就不存在问题。但是,如果只有一种类型的visitor对新的子类感兴趣,那么我们至少必须对该visitor和Visitor基类进行修改。此外,在这样的情况下,进行多处修改很可能是不可避免的。如果我们没有使用VISITOR模式,而是把所有功能塞到了Node类层次结构中,那么可能我们最终也要对Node类层次结构进行多处修改。

我们要考虑到的第二点是,VISITOR模式在Visitor和Node类层次结构之间创建了一个循环依赖关系。因此,对任何一个基类的接口进行修改,很可能会促使编译器对这两个类层次结构都进行重新编译。当然,和修改一个大杂烩基类相比,这可能也差不到哪里去。但在一般情况下,我们希望避免这样的依赖关系。

※   ※   ※

下面是Kevlin Henney [Henney96]的一些相关见解:

C++重载机制并没有强迫我们必须重载visit的所有版本,或者必须放弃重载visit成员。

using声明不仅用来支持名字空间的概念,它还允许我们把基类中的名字注入到当前类中来帮助重载。

class NewVisitor : public Visitor {
public:
  using Visitor::visit;    // pull in all visit functions
                  // for overloading

  virtual void visit(Subject**); // override Subject**variant
};

这种方法不仅保持了重载所提供的规整性,而且还可以防止扩散。它不会强迫用户去记住[visit]系列函数用了哪些名字或用了什么命名约定。这种方法使我们能在新版本中对Visitor进行修改,同时不会对客户代码产生影响。

※   ※   ※

我们已经运用了两个模式(即COMPOSITE模式和PROXY模式)来定义文件系统结构,还运用了一个模式来以一种无扩散的方法(即添加代码而不是修改代码)来引入新功能。其中蕴含了一条很好的面向对象设计准则,也许属于老生常谈,但却值得一提:通过在不修改已有代码的前提下改变一个系统的行为,可以使系统达到最佳的灵活性和可维护性。如果在别人使用了你的软件之后,你仍然能够这样说,那么恭喜你——你已经兑现了对象技术的诸多承诺!

扯远了。我们的文件系统的另一个主要设计问题与安全性有关。它至少有两个相关的子问题。

(1)对文件系统进行保护,使之避免遭到无意或恶意的破坏。

(2)在面临硬件和软件故障时,依然能够维护文件系统的完整性。

这里我们将集中讨论第一个子问题,第二个子问题留给读者作为练习。(如果有谁愿意接受这个挑战,我将很乐意为他的解决方案评分。)

时间: 2024-10-23 15:02:37

《设计模式沉思录》—第2章2.5节关于VISITOR的一些警告的相关文章

《设计模式沉思录》—第1章1.1节对模式的十大误解

第1章 介绍设计模式沉思录在阅读本书之前,如果读者还没有听说过一本名叫<设计模式>(Design Patterns: Elements of Reusable Object-Oriented Software [GoF95])的书,那么现在正好可以去找一本来读.如果读者听说过该书,甚或自己还有一本但却从来没有实际研读过,那么现在也正好应该好好研读一下. 如果你仍然在继续往下阅读,那么我会假设你不是上述两种人.这意味着你对模式有大致的了解,特别是对23个设计模式有一定的了解.你至少需要具备这样的

《设计模式沉思录》—第2章2.1节基础

第2章 运用模式进行设计设计模式沉思录如果想体验一下运用模式的感觉,那么最好的方法就是运用它们.对我来说,最大的挑战在于找到一个所有人都能够理解的示例.人们对自己的问题最感兴趣,如果某些人对某个示例越感兴趣,这个示例往往就越具体.问题在于,这样的示例所涉及的问题往往太过晦涩,对于没有相关领域背景的人来说难以理解. 层级文件系统(hierarchical file system)是每个计算机用户都熟悉的东西,就让我们来看看该如何设计它.我们不会关心诸如I/O缓冲和磁盘扇区管理之类的底层实现问题,我

《设计模式沉思录》目录—导读

版权声明设计模式沉思录Authorized translation from the English language edition, entitled Pattern Hatching: Design Patterns Applied, 9780201432930 by John Vlissides, published by Pearson Education, Inc., publishing as Addison-Wesley Professional. Copyright 1998

《设计模式沉思录》—第2章2.7节多用户文件系统的保护

2.7 多用户文件系统的保护我们已经讨论了如何给我们正在设计的文件系统添加简单的单用户保护.前面提到我们会将这个概念扩展到多用户环境,在这个环境中许多用户共享同一个文件系统.无论是配以中枢文件系统的传统分时系统,还是当代的网络文件系统,对多用户的支持都是必不可少的.即使那些为单用户环境所设计的个人计算机操作系统(如OS/2和Windows NT),现在也已经支持多用户.无论是什么情况,多用户支持都给文件系统保护这一问题增加了难度. 我们将再一次采用最简易的设计思路,效仿Unix系统的多用户保护机

《设计模式沉思录》—第2章2.8节小结

2.8 小结我们已经将模式应用于文件系统设计的各个方面.COMPOSITE模式的贡献在于定义了递归的树状结构,打造出了文件系统的主干.PROXY对主干进行了增强,使它支持符号化链接.VISITOR为我们提供了一种手段,使我们能够以一种得体的.非侵入性的方式来添加与类型相关的新功能. TEMPLATE METHOD在基本层面(即单个操作层面)为文件系统的保护提供了支持.对于单用户保护来说,我们只需要该模式就足够了.但为了支持多用户,我们还需要更多的抽象来支持登录.用户以及组.SINGLETON在两

《设计模式沉思录》—第2章2.3节“但是应该如何引入代用品呢?”

2.3 "但是应该如何引入代用品呢?"很高兴你能提出这个问题,因为我们现在正打算添加一个新的功能--符号化链接(symbolic link,它在Mac Finder中被称为别名,在Windows 95中被称为快捷方式).符号化链接基本上是对文件系统中另一个节点的引用.它是该节点的"代用品"(surrogate),它不是节点本身.如果删除符号化链接,它会消失但不会影响到它所引用的节点. 符号化链接有自己的访问权限,这个访问权限与它引用的节点的访问权限可能是不同的.但是

《设计模式沉思录》—第2章2.4节访问权限

2.4 访问权限到目前为止我们已经运用了两个设计模式:我们用COMPOSITE来定义文件系统的结构,用PROXY来帮我们支持符号化链接.把我们讨论到现在的改动和其他一些改进合并起来,得到了如图2-4所示的体现了COMPOSITE模式和PROXY模式的类层次结构. getName和getProtection用来返回节点的对应属性.Node基类为这些操作定义了默认的实现.streamIn用来把节点的内容写入文件系统,streamOut用来从文件系统读出节点的内容.(我们假设文件是按照简单的字节流来建

《设计模式沉思录》—第2章2.2节孤儿、孤儿的收养以及代用品

2.2 孤儿.孤儿的收养以及代用品现在让我们深入研究一下在我们的文件系统中运用COMPOSITE模式可能会得到什么样的结果.我们首先考察在设计Node类的接口时必须采取的一个重要折中,接着会尝试给刚诞生的设计增加一些新功能. 我们使用了COMPOSITE模式来构成文件系统的主干.这个模式向我们展示了如何用面向对象的方法来表示层级文件系统的基本特征.这种模式通过继承和组合来将它的关键参与者(Component.Composite及Leaf类)联系在一起,从而支持任意大小和复杂度的文件系统结构.它同

《设计模式沉思录》—第2章2.6节单用户文件系统的保护

2.6 单用户文件系统的保护经常使用计算机的人大都有过丢失重要数据的惨痛经历,起因可能只是一个不巧的语法错误,也可能是鼠标点偏了,或者只是深夜脑子突然不好使.在正确的时间删除一个错误的文件是一种常见的灾难.另一种情况是无意的编辑--在不经意间修改了一个不应该修改的文件.虽然一个高级文件系统会具备撤销功能,可以从这些不幸的事件中恢复,但我们通常更希望防患于未然.可悲的是,大多数文件系统给我们另一种不同的选择:预防或后悔⑥. 目前我们将集中精力讨论对文件系统对象(即节点)的删除和修改操作进行保护.之