// Purpose. Template Method design pattern lab // // Problem. 2 different spell-checking objects have a lot of common // functionality. This means there is: lots of duplicate code, no reuse, // and a maintenance nightmare if changes common to both classes become // necessary. // // Assignment. // o Create a common base class SpellChecker // o Subclass SimpleSpellChecker and SophisticatedSpellChecker off of it // o Move all common functionality to the base class // o Wherever differences exist (i.e. bubbleSortTheInput(), // diffWithUnixDictionary(), proposeCorrectSpellings()), specify // "placeholders" in base class // o Implement differences in concrete derived classes // // Hints. // o "Placeholders" could be pure virtual member functions // o "Placeholders" could be virtual member functions that are overridden // in the derived class, but "called back to" in the derived // implementation // o If you have: // SimpleSomething::doItSimple() { cout << "doItSimple"; } // HardSomething::doItHard() { cout << "doItHard"; } // Consider creating something of the form: // Something::doIt() = 0; // SimpleSomething::doIt() { cout << "doItSimple"; } // HardSomething::doIt() { cout << "doItHard"; } #include class SimpleSpellChecker { public: void doIt() { removeControlCodes(); convertToLowerCase(); tokenizeInput(); bubbleSortTheInput(); collapseDuplicateEntries(); diffWithUnixDictionary(); proposeCorrectSpellings(); } private: void removeControlCodes() { cout << "removeControlCodes:" << endl; } void convertToLowerCase() { cout << "convertToLowerCase:" << endl; } void tokenizeInput() { cout << "tokenizeInput:" << endl; } void bubbleSortTheInput() { cout << "bubbleSortTheInput:" << endl; } void collapseDuplicateEntries() { cout << "collapseDuplicateEntries:" << endl; } void diffWithUnixDictionary() { cout << "diffWithUnixDictionary:" << endl; } void proposeCorrectSpellings() { cout << "proposeCorrectSpellings:" << endl; cout << " convert token to phonetic spelling" << endl; cout << " generate all permutations" << endl; cout << " use eenie-meenie to pick the best choices" << endl; } }; class SophisticatedSpellChecker { public: void doIt() { removeControlCodes(); convertToLowerCase(); tokenizeInput(); mergeSortTheInput(); collapseDuplicateEntries(); diffWithOxfordDictionary(); proposeCorrectSpellings(); } private: void removeControlCodes() { cout << "removeControlCodes:" << endl; } void convertToLowerCase() { cout << "convertToLowerCase:" << endl; } void tokenizeInput() { cout << "tokenizeInput:" << endl; } void mergeSortTheInput() { cout << "mergeSortTheInput:" << endl; } void collapseDuplicateEntries() { cout << "collapseDuplicateEntries:" << endl; } void diffWithOxfordDictionary() { cout << "diffWithOxfordDictionary:" << endl; } void proposeCorrectSpellings() { cout << "proposeCorrectSpellings:" << endl; cout << " convert token to phonetic spelling" << endl; cout << " generate all permutations" << endl; cout << " rank order the permutations" << endl; cout << " use AI to pick the best choices" << endl; } }; void main( void ) { SimpleSpellChecker okay; SophisticatedSpellChecker good; cout << "********** Simple Spell Check **********" << endl; okay.doIt(); cout << "********** Sophisticated Spell Check **********" << endl; good.doIt(); } // ********** Simple Spell Check ********** // removeControlCodes: // convertToLowerCase: // tokenizeInput: // bubbleSortTheInput: // collapseDuplicateEntries: // diffWithUnixDictionary: // proposeCorrectSpellings: // convert token to phonetic spelling // generate all permutations // use eenie-meenie to pick the best choices // ********** Sophisticated Spell Check ********** // removeControlCodes: // convertToLowerCase: // tokenizeInput: // mergeSortTheInput: // collapseDuplicateEntries: // diffWithOxfordDictionary: // proposeCorrectSpellings: // convert token to phonetic spelling // generate all permutations // rank order the permutations // use AI to pick the best choices