サブクラスサンドボックスパターンについて学んでみる

はいどーもこんにちは、我が家というボックスに閉じこもっている無職です。
本日は『Game Programming Patterns』で紹介されているサブクラスサンドボックスパターンについて勉強してみたいと思います。

テンプレートメソッドパターン

いきなりですが、みなさんはテンプレートメソッドパターンは使っていますでしょうか?
意図してるかどうかはともかく、おそらくほとんどの人はこのパターンを一度は使ったことがあると思います。
例えば以下のようなコードがテンプレートメソッドパターンです。

抽象クラスであるHogeBaseはDoSomethingメソッドをpublicメソッドとして公開しています。
外部のコードが実際に使用するのはこのDoSomethingメソッドのみです。
他のメソッドはprotectedであり、このクラスを継承しているクラス以外からは見ることができません。
そしてそれぞれのprotectedメソッドはオーバーライドすることを前提としています(抽象メソッドとして定義してもよかったのですが、今回はvirtualなメソッドとして定義しています)。
継承先のクラスでDoSomethingの中身を変更することは意図されていませんが、protectedメソッドの中身は自由に作ることができるのです。

以上見たように、基本となる動きを定義しておき、その基本となる動きで使う各メソッドを継承先でオーバーライドしていくのがテンプレートメソッドパターンです。
外部のライブラリを使ったとき、恐らくはこれと似たようなパターンを使ったことがあるんじゃないかなーと思います。

サブクラスサンドボックスパターン

先ほどのテンプレートメソッドパターンでは「基本となる動きを定義しておき、その基本となる動きで使う各メソッドを継承先でオーバーライドしていく」と書きました。
ちょうどこの反対となるのがサブクラスサンドボックスパターンです。
すなわち「基本となる動きはサブクラスが自由に作れるが、サブクラス内で使用するメソッドは継承元のクラスが提供する」パターンです。

実際のコードは以下のような感じです。

基底クラスFugaBaseはDoSomethingメソッドを抽象クラスとして定義しています。
継承先ではこのDoSomethingメソッドの中身を書いていくことになります。
そのとき使えるユーティリティメソッドとして、protectedなInitializeメソッド・Executeメソッド・Terminateメソッドがあります。
これらのユーティリティメソッドは外部からアクセスできず、継承先にのみ公開されています。
また、ユーティリティメソッドの中身が変更されることは意図していません。

どうでしょう!
まさにテンプレートメソッドパターンの逆になってはいませんでしょうか!?

終わりに

「継承はややこしくなるからダメ」みたいな話はよく聞くのですが、『Game Programming Patterns』は「深く伸びた木構造」ではなく「浅く広がった継承木」なら扱いやすいのではないか、と書いています。
サブクラスサンドボックスはまさに「浅く広がった継承木」を作っていくときに役立つパターンです。

確かに深く伸びた木構造はコードを把握するのがめちゃくちゃ大変ですし、ロジックを追うのも疲れます。
一方で「浅く広がった継承木」ならば、結局のところ見る必要があるクラスは2つです(一回しか継承してないなら)。
全く継承を0にしてプログラミングをするのは難しそうなので、僕も「浅く広がった継承木」を意識して組みたいなと思いましたよ。

ほなそんな感じでまた。

フォローする