ホーム < ゲームつくろー! < デザインパターン習得編
Proxy
〜オブジェクトへのアクセスの代理人
@ 描画負荷を減らす代理人
Proxyというのは「代理人」という意味です。Proxyパターンは「クライアントとオブジェクトの間に入って、オブジェクトのアクセスを代理する」パターンです。
このパターンを用いた有名な実装が「スマートポインタ」です。スマートポインタオブジェクト(Proxy Object)に動的に確保したオブジェクトを登録し、間接参照演算子やGetPtr関数などを利用して、間接的に登録オブジェクトにアクセスします。
ゲーム製作でProxyパターンというと、例えばシミュレーションゲームなどが考えられます。シミュレーションゲームには広大なフィールドに非常に多くのキャラクタが存在します。しかし、プレーヤーはフィールドの一部しか見ていません。普通キャラクターの描画はコストがかかりますから、見えていない部分まで描画するのは無駄以外の何物でもありません。しかし、位置や行動の計算は必要になるので、オブジェクトは必要となります。
キャラクタオブジェクトが持つDraw関数内に描画のタイミングを判定させるのは、もちろん良くありません。かと言って、ゲーム全体を管理するクライアントに判断させるのも、出来なくはないですが柔軟性に欠けてしまうでしょう。よって、「タイミングを知っている代理人に判定させる」のが最良であろうと思います。ここでProxyパターンの登場です。
CharacterProxyクラスはキャラクタオブジェクトと同じ親クラスから派生され、共通するインターフェイスを持っています。さらに、キャラクタオブジェクトへのポインタを保持します。
クライアントはキャラクタを生成した時に同時にCharacterProxyオブジェクトも作り、生成したキャラクタをそれに登録します。そして、CharacterProxyオブジェクトに対して「描画しろ(Draw関数の実行)」と命令するわけです。CharacterProxyオブジェクトのDraw関数内では現在の位置情報から描画すべきか否かを判断して、描画OKならば登録されているキャラクタオブジェクトのDraw関数を呼び出します。
Proxyパターンの関係図を示します。
A Proxyパターンの種類
Proxyパターンにはいくつかの種類があることが知られています。
上のCharacterProxyの例は「virtual proxy」と呼ばれています。本当の実体(Enemyオブジェクト)を生成したり描画したりする事にコストがかかるとき、それに仮想的になりすましてそれを軽減させる働きをなします。
remote proxyは、本当の実体の格納場所をうまく隠蔽して、クライアントの要求を単純化する働きをなします。例えば、サウンドノベルスで文字列を呼び出すとき、それはメモリ上にあるかもしれませんし、ファイルに格納されているかもしれません。クライアントがその格納場所を判断するよりは、Proxyオブジェクトに「文字列をくれ」と命令するだけの方が楽ですよね。メモリ上かファイル上かはProxyオブジェクトが判断すれば良いだけの話です。格納場所が別のところ(あるサーバー機など)にあっても、Proxyオブジェクトを入れ替えるだけでよく、クライアントのプログラムをほとんど汚しません。
protection proxyは、Porxyクラスのインターフェイス内で実体へのアクセスを制御する方法です。大切な情報へのアクセスをProxyオブジェクトが判断して、認められたクライアントだけに情報を返します。
smart referenceは、いわゆるスマートポインタのような振る舞いのことですが、ポインタを通した間接参照時に何か付加的な実行を伴う方法全般を言います。Proxyオブジェクトをsingletonパターンなどで生成する事で、例えば実体への排他的アクセスを実現できます。キャラクタの位置を更新している最中にオブジェクトへのアクセスがあった場合、Proxyオブジェクトがそれを一時的に止めてくれるわけです。