Design Patterns
2
Authors often view the document in terms of its logical structure as well, that is, in terms of sentences,
paragraphs, sections, subsections, and chapters. To keep this example simple, our internal representation won't
store information about the logical structure explicitly. But the design solution we describe works equally well
for representing such information.
3
Calder was the first to use the term "glyph" in this context [CL90]. Most contemporary document editors don't
use an object for every character, presumably for efficiency reasons. Calder demonstrated that this approach is
feasible in his thesis [Cal93]. Our glyphs are less sophisticated than his in that we have restricted ours to strict
hierarchies for simplicity. Calder's glyphs can be shared to reduce storage costs, thereby forming directed-
acyclic graph structures. We can apply the Flyweight (151) pattern to get the same effect, but we'll leave that as
an exercise for the reader.
4
The interface we describe here is purposely minimal to keep the discussion simple. A complete interface would
include operations for managing graphical attributes such as color, font, and coordinate transformations, plus
operations for more sophisticated child management.
5
An integer index is probably not the best way to specify a glyph's children, depending on the data structure the
glyph uses. If it stores its children in a linked list, then a pointer into the list would be more efficient. We'll see a
better solution to the indexing problem in Section 2.8, when we discuss document analysis.
6
The user will have even more to say about the document's logical structure—the sentences, paragraphs,
sections, chapters, and so forth. The physical structure is less interesting by comparison. Most people don't care
where the linebreaks in a paragraph occur as long as the paragraph is formatted properly. The same is true for
formatting columns and pages. Thus users end up specifying only high-level constraints on the physical
structure, leaving Lexi to do the hard work of satisfying them.
7
The compositor must get the character codes of Character glyphs in order to compute the linebreaks. In Section
2.8 we'll see how to get this information polymorphically without adding a character-specific operation to the
Glyph interface.
8
That is, redoing an operation that was just undone.
9
Conceptually, the client is Lexi's user, but in reality it's another object (such as an event dispatcher) that
manages inputs from the user.
10
We could use function overloading to give each of these member functions the same name, since their
parameters already differentiate them. We've given them different names here to emphasize their differences,
especially when they're called.
11
IsMisspelled implements the spelling algorithm, which we won't detail here because we've made it
independent of Lexi's design. We can support different algorithms by subclassing SpellingChecker;
alternatively, we can apply the Strategy (246) pattern (as we did for formatting in Section 2.3) to support
different spelling checking algorithms.
Pag 75