テンプレートメソッド
何らかの理由で使用したデザインパターンを人に尋ねる必要がある場合、テンプレートメソッドパターンを呼び出す人はほとんどいません。 これはおそらく、パターンの命名法に関する知識のギャップが原因です。個人的には、経験豊富なプログラマーがこのような便利で有用なパターンを決して使用しないとは想像できません。 私は彼を詳しく見ることを提案します。
だから、テンプレートメソッド。 c ++テンプレートとは関係ありません。 このパターンは、非常にシンプルで直感的で、非常に便利であるという点で注目に値します。 これは、動作パターンのカテゴリに属し、1つの簡単な目的に役立ちます。このアルゴリズム自体の構造を定義する基本クラスから派生したクラスファミリ内の特定のアルゴリズムのステップを再定義します。
特定の行のテキストを暗号化するように設計されたCryptクラスを書いているとします。 暗号化関数はクラスで定義されます:
void encrypt() { // setupRnd(); setupAlgorithm(); // std::string fContent = getString(); // std::string enc = applyEncryption(fContent); // saveString(fContent); // wipeSpace(); }
Pattern Methodメソッドを使用すると、encrypt()関数で提示されるアルゴリズムを使用して、キーボードから、ディスクから読み取り、ネットワーク経由で受信したさまざまなソースから受信した文字列を処理できます。 同時に、アルゴリズム自体の構造と不変のステップ(初期パラメーターの設定、作業のトレースのクリーンアップ、および必要に応じて暗号化の使用)は変更されません。 これにより、次のことが可能になります。
- 異なるサブクラスで変わらないコードを再利用します。
- 一度定義されたコードを使用して、サブクラスのファミリーの一般的な動作を定義します。
- アクセス権の差別化-可変アルゴリズムステップを実装する場合、閉じた仮想関数を使用します。 これにより、このような操作は、変更可能なアルゴリズムのステップとしてのみ呼び出されます(または、不適切な場所の派生クラスによって呼び出されることはありません)。
そのため、Cryptクラスに必要なメンバーを追加します。
private: void setupRnd() { // std::cout << "setup rnd\n"; }; void setupAlgorithm() { // std::cout << "setup algorithm\n"; }; void wipeSpace() { // std::cout << "wipe\n"; }; virtual std::string applyEncryption(const std::string& content) { // std::string result = someStrongEncryption(content); return result; } virtual std::string getString() = 0; virtual void saveString(const std::string& content) = 0;
関数はプライベートであることに注意してください。 これは、呼び出しに対する意図的な制限であり、派生クラスでオーバーライドすることを妨げません。
そして、実際には、派生クラス-ディスク上の暗号化ファイル:
class DiskFileCrypt : public Crypt { public: DiskFileCrypt(const std::string& fName) : fileName(fName) {}; private: std::string fileName; virtual std::string getString() { std::cout << "get disk file named \"" << fileName << "\"\n"; // return fileContent; } virtual void saveString(const std::string& content) { std::cout << "save disk file named \"" << fileName << "\"\n"; // } };
呼ばれたときにすでに明らかです
DiskFileCrypt d("foo.txt"); d.encrypt();
encrypt()関数アルゴリズムが実行され、コンソールに以下が表示されます。
setup rnd
setup algorithm
get disk file named "foo.txt"
save disk file named "foo.txt"
wipe
上記の例の仮想関数メカニズムは、クラスの動作をカスタマイズするためだけに役立ちます。 それらを純粋に仮想として定義することにより、クラスを継承するための要件を指定できます。 たとえば、相続人に暗号化アルゴリズムを定義させたい場合、applyEncryptionクラスの純粋な仮想メンバー関数を作成する必要があります。