ポリシークラスとホストクラス〜ポリシーベースドクラスデザイン

ある決まったインタフェースのセットをクラスが持つように要求するとき、そのインターフェースのセットそのものをまとめて、「ポリシー」と呼ぶ。そのポリシーを持っているクラスそのものを「ポリシーの実装」や 「ポリシークラス」と呼んだりもする。

たとえば、void Hello( void ); というメソッドを必ず持って下さいという要請を、Helloポリシーと名づけることにすると、このメソッドを持っている全てのクラスはHelloポリシーを実装しているねということになるし、
float GetRadius( void );
Vec3D GetCenter( void );
という2つのメソッドを持つことを、Circleポリシーと呼ぶことにすると、これを満たしているクラスは皆、それだけでもうCircleポリシーの実装ということになる。このように、あるポリシーをそのクラスが満たすためには、「そのメソッドをそのクラスに持たせる」だけでよいわけである。

ホスト」テンプレートクラス(ホストクラス)は、その実体化の引数としてポリシークラスを受け取ります。そして、受け取ったポリシークラスを、継承したりメンバとして持つようにし(*注1)、内部の機能やアルゴリズムの中において、ポリシークラスを利用する(入力にしたり出力にしたりする)のです。つまり、あらゆるクラスはホストが要求するポリシーを実装するだけで、ホストのアルゴリズムや機能を利用することができるわけです。
アプリケーションコードを記述するユーザーは、ホストクラステンプレートをポリシークラスで実体化して使います。

さて、以上の、例として、ひとつの具体的なケースを挙げて見ます。

ここで、ImportPolicy ポリシーを、
static void AddTriangle( const float coord[12], ImportPolicy* );
という、静的メソッドを持つポリシーと規定します。

ReadSTL テンプレートクラスは、任意のImportPolicy クラスに対し、STLから三角を一つ読み込んでは、上記のAddTriangle メソッドを呼び出すように書かれた、ホストクラスであるとします。利用側のクラスにおいては、STLのフォーマットを知る必要は全くなしに、ただ単に、引数としてで渡される、12個のfloat値(法線、頂点x3)の情報を、己のポリシー実装である、AddTriangle() の中で、好きなように己の構造体の中に格納して行けばよいのです。

ReadSTLホストクラスの利用側コードにて…、まずはMyMesh::AddTriangle()ポリシー実装の中に、オリジナルな三角形追加用のコードを記述しておく。あとは、MyMesh のインスタンスのポインタmy_mesh を用意すれば、my_mesh へのSTLファイル読み込みは、以下の1行で完了する。
ReadSTL< MyMesh > GoForIt( filename, my_mesh );
つまり、ReadSTLを使えば、どのようなクラス・構造体であったとしても、誰でも、STLファイルフォーマットを知らない人でも、非常に手軽に、STLファイルを読み込むことができるのである。

(*注1)ポリシーの静的メソッドを中で呼ぶだけなら別に継承や包含などさえしなくてよいのだが。
(補遺)ReadSTLを考えた本方式は、汎用目的でありながら、本質的に無駄な中間バッファを介させない、つまりパーサから直接構造体に読み込む方式を実現しているため、メモリ効率ならびに速度効率的にも超効果的であったという実験結果をここに追記しておきたい。

Modern C++ Design: Generic Programming and Design Patterns Applied (C++ In-Depth Series)

Modern C++ Design: Generic Programming and Design Patterns Applied (C++ In-Depth Series)