Design Patterns: Elements of Reusable Object-Oriented Software 86 void GlyphSubclass::CheckMe (SpellingChecker& checker)
{ checker.CheckGlyphSubclass(this); }
where GlyphSubclass would be replaced by the name of theglyph subclass. Note that
when CheckMe is called, thespecific Glyph subclass is known
—
after all, we're in
one of itsoperations. In turn, theSpellingChecker class interface includes an
operation likeCheckGlyphSubclass for every Glyphsubclass
10
:
class SpellingChecker {
public:
SpellingChecker();
virtual void CheckCharacter(Character*);
virtual void CheckRow(Row*);
virtual void CheckImage(Image*);
// ... and so forth
List& GetMisspellings();
protected:
virtual bool IsMisspelled(const char*);
private:
char _currentWord[MAX_WORD_SIZE];
List _misspellings;
};
SpellingChecker's checking operation forCharacter glyphs might look something
like this:
void SpellingChecker::CheckCharacter (Character* c) {
const char ch = c->GetCharCode();
if (isalpha(ch)) {
// append alphabetic character to _currentWord
} else {
// we hit a nonalphabetic character
if (IsMisspelled(_currentWord)) {
// add _currentWord to _misspellings
_misspellings.Append(strdup(_currentWord));
}
_currentWord[0] = '\0';
// reset _currentWord to check next word
}
}
Design Patterns: Elements of Reusable Object-Oriented Software 87 Notice we've defined a special GetCharCode operation onjust the Character class.
The spelling checker can deal withsubclass-specific operations without resorting
to type tests orcasts
—
it lets us treat objects specially.
CheckCharacter accumulates alphabetic charactersinto the _currentWord buffer.
When it encounters anonalphabetic character, such as an underscore, it uses
theIsMisspelled operation to check the spelling of theword in _currentWord.
11
If
the word ismisspelled, then CheckCharacter adds the word to thelist of misspelled
words. Then it must clear out the_currentWord buffer to ready it for the next
word.When the traversal is over, you can retrieve the list of misspelledwords
with the GetMisspellings operation.
Now we can traverse the glyph structure, callingCheckMe on each glyph with the
spelling checker as an argument.This effectively identifies each glyph to the
SpellingChecker andprompts the checker to do the next increment in the spelling
check.
SpellingChecker spellingChecker;
Composition* c;
// ...
Glyph* g;
PreorderIterator i(c);
for (i.First(); !i.IsDone(); i.Next()) {
g = i.CurrentItem();
g->CheckMe(spellingChecker);
}
The following interaction diagram illustrates howCharacter glyphs and the
SpellingChecker objectwork together: