Node
, which is the key element of our tree structure. The tree is a compositional data type (every Node
instance can have multiple child nodes and, hence, a parent node) with heterogeneous data items (nodes of different types). Node
subtypes are Notebook
, Page
, and Cell
. The Cell
type is an abstract type inherited from by different content cells, namely TextCell
(for text), SourceCodeCell
(representing source code), and ImageCell
(for images). It is more than likely that other content cells will be added in the future.exportToHtml()
method to the Node
type:Node
(e.g. ImageCell
, TextCell
) can produce a specific HTML output. After all, an ImageCell
will very likely produce HTML that is markedly different from that of a TextCell
.Dog
andCat
inherit from a common base class Mammal
and this class defines a method makeSound()
(the single interface part), then Dog
would implement it producing a barking sound, while Cat
would implement it making a meow sound (the different forms of behavior part).exportToHtml()
method abstract and have your different Node
subtypes implement it to their specific needs. Here are two examples:Node
type and its various sub types.Node
subtypes usually deal with. Their core logic revolves around the management of Page
s (for Notebook
s), Cells
(for Page
s), text (for TextCell
s), source code (for SourceCodeCell
s), etc. The export logic you just added feels misplaced (not to mention the fact that the various target formats of HTML, Xml, and the like, are themselves incompatible to one another!).Node
subtypes logic now violates yet another principle: the Single-Responsibility Principle:HTMLExporter
class that exports your entire Notebook
object to HTML. The feature works well, but after some time a new version of HTML comes along, thus forcing you to update your export logic.HTMLExporter
writes its contents directly to the disk, and this logic is no longer compatible.Node
subtypes is that whenever the requirements regarding the node subtype logic change, you would have to modify the subtypes. Likewise, whenever the requirements for any of the export features change (new version of HTML, Markdown, Xml, or the like), you would have to modify the subtypes yet again. Those are too many reasons for your classes to change, hence too many responsibilities.TextCell
s, SourceCodeCell
s, ImageCell
s, Page
s, ...) that needs to accommodate different types of operations (exportToHtml()
, exportToXml()
, exportToMarkdown()
, ...). These operations are very specific to the types they operate on and the entire set is principally open-ended, meaning that it is more than likely that more operations will have to be added at a later point.Node
subtypes in order to export the entire Notebook
.NodeExporter
:NodeExporter
subtypes according to the formats required. Let's begin with the HTML export feature:HtmlExporter
class, namely exporting various node types to HTML.NodeExporter
implementation (e.g. XmlExporter
and HtmlExporter
) operate on our class hierarchy. Specifically, we need to loosely couple those implementations to our class hierarchy, so as to follow the OPC.Notebook
instance, traverse its tree structure and feed every node inside of it to the desired NodeExporter
implementation. As Notebook
and all types contained therein derive from Node
, we can just extend its interface as follows:Node
sub types an instance of any concrete NodeExporter
implementation, and this in turn would call the proper method on the NodeExporter
instance passing itself along to it. Such double calling of methods is called Double Dispatch and has a long history in OOP.Notebook
and add some Page
s and Cell
s to it:Notebook
instance to Html:NodeExporter
interface in another type. We will not have to touch any part of our existing Node
s class hierarchy.Node
sub types requires us to extend the NodeExporter
interface with just another method name (or method overload in languages that support these) to make sure that existing format exporters retain compatibility with the new tree structure.JsonExporter
, or add a LinkCell
to the class hierarchy of our Notebook
app.