我的设计中是否需要访客模式?

时间:2017-09-29 08:45:15

标签: c++ oop design-patterns

我正在设计用于学习目的的html解析器。我第一次创建整体设计。

存储html元素的数据结构。

Base:HtmlBaseElement

Derived:HTMLElement,PElement,HtagElemement,ImgElement,BodyElement,StrongElement

基本上我会为html中的每种元素创建派生类。

我需要将此html文件写回文件,并允许用户在已解析的html文件中添加元素。

这就是我的想法:

第一种方法:

  1. 为每种元素创建一个具有访问功能的BaseVisitor

  2. 创建派生访客类WriteHtmlVisitor以编写整个文件,该文件将visit HTML数据结构中的每个元素。

  3. 第二种方法:

    我也可以使用具有WriteHtmlFile对象的类HTMLElement,然后使用所有元素的getter来编写它。

    这是编写html文件并在文件中添加新元素的最佳方法。

    我只是在寻找建议,因为这是在设计阶段。

    感谢。

2 个答案:

答案 0 :(得分:0)

这里实际上有四种模式:

  1. 具有所有重要字段的基类(第二种方法)
  2. 虚拟fn调用并传递基类ptr
  3. 动态访问者模式,正如您所写
  4. 静态访客模式

    1. 会在sw建筑师中产生温和的反感,而在实践中它可能会很好地工作并且很快。这里的问题是你总是会有一个新的派生类,其中包含需要新数据的新派生原理图(或现有数据的不同内容),因此你的基类将不断变化,很快就会出现这种情况。 ll使用switch语句重新实现动态分派。在专业方面,它是最快的,如果您获得正确的基础数据结构,它将长时间工作。一个经验法则是,如果你能(不一定会)将print()的所有输入从派生的ctor传递给base ctor,你就可以了。这里有效,因为你只填写属性和内容(我想)。

    2. 只要你有很少的方法与课程非常接近,那么它很慢并且只是很好。它可能在这里添加一个纯虚拟print()到基类并在派生类中实现;然而,如果你写第147个虚拟,你的代码变成意大利面。 虚拟的另一个问题是它是一个开放式的层次结构,这可能导致你的lib的客户端实现后代。一旦他们开始这样做,你在设计设计方面的灵活性就会大大降低。

    3. 就是你写的。它比虚拟慢一点,但在大多数情况下仍然可以接受。对于许多初级程序员来说,理解幕后的内容是一个障碍。此外,您已经绑定到特定签名(这不是问题);否则很容易添加新的实现,并且您不会向基类引入新的依赖项。如果您有许多类似打印的操作(访问者),则此方法有效。如果你只有这个,也许它对于任务来说有点复杂,但要记住,只要有一个,那就更多了。这是一个封闭的层次结构,访问者正在订阅' (编译时错误)如果添加了新的后代,这有时很有用。

    4. 基本上是3 w / o虚拟,所以它很快。你要么传递变体,要么只传递具体的类。 (3)中列出的所有设计考虑因素都适用于这一点,除了制作青少年/中间体更加困难。编码员理解它(模板焦虑),与(2) - (4)相比,它非常快。

  5. 在一天结束时,归结为:

    • 您想要一个开放或封闭的层次结构
    • 初级/高级比率和公司。文化(或读者之间)
    • 必须多快
    • 您设想了多少个操作/签名

    没有单一答案(一种尺寸不适合所有人),但考虑上述问题可以帮助您做出决定。

答案 1 :(得分:0)

我会建议以下:

- 访客模式 - 在此上下文中,虽然您可以应用它,但此模式的基本目的是将操作作为此模式的一部分进行操作,而这不是此类情况。您只关心写操作(具有不同的实现),但这里似乎不是动态操作的情况。

- 策略模式 - 您可以改用策略模式,最初,您可以从SimpleDiskStorageStrategy开始,在设计进化时,您可以在将来拥有多种策略,例如{{1 }或CachingStorageStrategy

- 复合模式 - 由于您的要求是遍历和动态处理结构中的元素(添加/删除元素),我认为这是一个结构问题而不是行为问题。因此,尝试使用Composite&构建器模式(如果复杂性增加)。

- Flyweight模式 - 用它来创建和维护所有html对象的引用(您可以为每个HTML文档类型传递State对象)。这将有助于在解析许多html文档时更好的内存管理,并有效地更好地存储在磁盘上。