我正在设计用于学习目的的html解析器。我第一次创建整体设计。
存储html元素的数据结构。
Base
:HtmlBaseElement
Derived
:HTMLElement,PElement,HtagElemement,ImgElement,BodyElement,StrongElement
基本上我会为html中的每种元素创建派生类。
我需要将此html文件写回文件,并允许用户在已解析的html文件中添加元素。
这就是我的想法:
第一种方法:
为每种元素创建一个具有访问功能的BaseVisitor
。
创建派生访客类WriteHtmlVisitor
以编写整个文件,该文件将visit
HTML数据结构中的每个元素。
第二种方法:
我也可以使用具有WriteHtmlFile
对象的类HTMLElement
,然后使用所有元素的getter来编写它。
这是编写html文件并在文件中添加新元素的最佳方法。
我只是在寻找建议,因为这是在设计阶段。
感谢。
答案 0 :(得分:0)
这里实际上有四种模式:
静态访客模式
会在sw建筑师中产生温和的反感,而在实践中它可能会很好地工作并且很快。这里的问题是你总是会有一个新的派生类,其中包含需要新数据的新派生原理图(或现有数据的不同内容),因此你的基类将不断变化,很快就会出现这种情况。 ll使用switch语句重新实现动态分派。在专业方面,它是最快的,如果您获得正确的基础数据结构,它将长时间工作。一个经验法则是,如果你能(不一定会)将print()的所有输入从派生的ctor传递给base ctor,你就可以了。这里有效,因为你只填写属性和内容(我想)。
只要你有很少的方法与课程非常接近,那么它很慢并且只是很好。它可能在这里添加一个纯虚拟print()到基类并在派生类中实现;然而,如果你写第147个虚拟,你的代码变成意大利面。 虚拟的另一个问题是它是一个开放式的层次结构,这可能导致你的lib的客户端实现后代。一旦他们开始这样做,你在设计设计方面的灵活性就会大大降低。
就是你写的。它比虚拟慢一点,但在大多数情况下仍然可以接受。对于许多初级程序员来说,理解幕后的内容是一个障碍。此外,您已经绑定到特定签名(这不是问题);否则很容易添加新的实现,并且您不会向基类引入新的依赖项。如果您有许多类似打印的操作(访问者),则此方法有效。如果你只有这个,也许它对于任务来说有点复杂,但要记住,只要有一个,那就更多了。这是一个封闭的层次结构,访问者正在订阅' (编译时错误)如果添加了新的后代,这有时很有用。
基本上是3 w / o虚拟,所以它很快。你要么传递变体,要么只传递具体的类。 (3)中列出的所有设计考虑因素都适用于这一点,除了制作青少年/中间体更加困难。编码员理解它(模板焦虑),与(2) - (4)相比,它非常快。
在一天结束时,归结为:
没有单一答案(一种尺寸不适合所有人),但考虑上述问题可以帮助您做出决定。
答案 1 :(得分:0)
我会建议以下:
- 访客模式 - 在此上下文中,虽然您可以应用它,但此模式的基本目的是将操作作为此模式的一部分进行操作,而这不是此类情况。您只关心写操作(具有不同的实现),但这里似乎不是动态操作的情况。
- 策略模式 - 您可以改用策略模式,最初,您可以从SimpleDiskStorageStrategy
开始,在设计进化时,您可以在将来拥有多种策略,例如{{1 }或CachingStorageStrategy
。
- 复合模式 - 由于您的要求是遍历和动态处理结构中的元素(添加/删除元素),我认为这是一个结构问题而不是行为问题。因此,尝试使用Composite&构建器模式(如果复杂性增加)。
- Flyweight模式 - 用它来创建和维护所有html对象的引用(您可以为每个HTML文档类型传递State对象)。这将有助于在解析许多html文档时更好的内存管理,并有效地更好地存储在磁盘上。