図1●町内会の連絡網の構造をモデリングする
図1●町内会の連絡網の構造をモデリングする
[画像のクリックで拡大表示]

 プログラミングテクニックの中には、「かっこいい!」と感動しちゃうものがありますね。たとえば、再帰、インターフェイス、メッセージフックなどです。再帰は、メソッドの処理の中で同じメソッドを呼び出すテクニックです。繰り返し処理をスマートに記述できます。インターフェイスは、複数のクラスに同じ構文のメソッドを強制的に実装させるテクニックです。多態性(異なるオブジェクトを同じ方法で使うこと)を実現できます。メッセージフックは、メソッドの呼び出しを横取りするテクニックです。既存のクラスのメソッドに任意の処理を挿入できます。今回紹介する2つのパターンは、これらのテクニックを応用しています。

【お役立ち度】★★★★★
●再帰とインターフェイスを応用したCompositeパターン

 奇抜な例で恐縮ですが、町内会の連絡網を思い浮かべてください。Aさん~Dさんの4件の家庭があって、順番にお知らせを伝えるとします。この様子をプログラムに置き換えられるようにモデリングすると、樹木の節に葉が付いた階層構造となります。個々の節は、その先につながる節の情報(節1なら、その次は節2であること)と、節に付いた葉の情報を持ちます。個々の葉は、家庭を表すものとなります(図1[拡大表示])。

 節をNodeクラス、葉をLeafクラスとしてプログラムにしてみましょう。これらのクラスを使う側の人は、町内会全体でも、個々の家庭でも、まったく同じ方法でお知らせを伝えられたら便利ですね。つまり、NodeクラスとLeafクラスが、まったく同じ構文のメソッドを持っていたら使いやすくなります。

 はい、お待たせしました。こういうときに使われるテクニックが、インターフェイスです。お知らせを受け取るインターフェイスをInformationListenerという名前にして、そのメンバとしてお知らせを受け取るsetInformationメソッドを定義しましょう(リスト1[拡大表示])。InformationListenerインターフェイスをNodeクラスとLeafクラスに実装させれば、まったく同じ構文のsetInformationメソッドを持つことが強制されます。

リスト1●インターフェイスはメソッドの実装を強制する

interface InformationListener {
    void setInformation(int info);
}

 このsetInformationメソッドは、個々の家庭にお知らせを伝えることも、連絡網全体にお知らせを伝えることもできなければなりません。それを実現するための工夫が、Composite(合成物)パターンです。住人を表すLeafクラスでは、ごく普通にsetInformationメソッドの処理内容を記述します(引数の値を受け取ればOKです)。それに対して、連絡網を形成するNodeクラスには、ちょっとした仕掛けが必要となります。

 Nodeクラスのフィールドとして、その先につながる節の情報(nextNode)と、節に付いた葉の情報(myLeaf)を持たせます。そして、NodeクラスのsetInformationメソッドの処理内容では、自分の葉のsetInformationメソッドを呼び出し、さらにその先につながる節のsetInformationメソッドを呼び出すのです。setInformationメソッドの中でsetInformationメソッドを呼び出しすことでお知らせの伝達が繰り返されるのですから、再帰のテクニックを応用していると言えます。連絡網の末尾は、次につながる節がnullであることで検出します(リスト2[拡大表示])。

リスト2●節を表すクラスには仕掛けが必要

public class Node implements InformationListener {
    // この先につながる節
    private Node nextNode;
    // この節に付いた葉
    private InformationListener myLeaf;

    public void setInformation(int info) {
        // この節に付いた葉のsetInformationメソッドを呼び出す
        myLeaf.setInformation(info);
        // この先につながる節のsetInformationメソッドを呼び出す
        if (nextNode != null) {
            nextNode. setInformation(info);
        }
        ・・・
    }
}

 どうです、かっこいいでしょう! ごく普通のLeafクラスも、階層構造を持ったNodeクラスも、まったく同じ方法で使えるのです。多態性も、このぐらいやってくれると感動しますね。評価は、星5つの満点です。

【お役立ち度】★★★★★
●インターフェイスとメッセージフックを応用したProxyパターン

 メッセージとは、オブジェクトから他のオブジェクトに送られる通知のことです。具体的には、メソッド呼び出しがメッセージに相当します。Proxy(代理人)パターンは、オブジェクトに送られるメッセージをフック(横取り)して任意の処理を挿入するための工夫です。そのために、フック用のクラス(これを「フッククラス」と呼ぶ)を作ります。

 例として、MyClassクラスが持つmyMethodメソッドをフックするとしましょう。フッククラスをHookClassとします。myMethodメソッドを持つMyInterfaceインターフェイスを定義しておき、それをMyClassクラスとHookClass クラスの両方で実装します。HookClass クラスのmyMethodメソッドの処理として、MyClassクラスのインスタンスを生成し、myMethodメソッドを呼び出します。この呼び出しの前後に、任意の処理を挿入できます。これが、メッセージフックです(リスト3[拡大表示])。

リスト3●メソッドの呼び出しの前後に処理を挿入する

public class HookClass implements MyInterface {
    public void myMethod(int a) {
        // メソッドの呼び出し前に機能を挿入できる
        ・・・

        // MyClassクラスのmyMethodメソッドを呼び出す
        MyClass a = new MyClass();
        a.myMethod(a);

        // メソッドの呼び出し後に機能を挿入できる
        ・・・
    }
}

 ここまでの説明を読んで「あれ? どこかで見たことがあるパターンだなぁ...」と思われたなら大正解です。実は、Proxyパターンの工夫は、前回紹介したDecoratorパターンと基本的に同じなのです(両者を比べてみてください)。では、どこが違うのか。ここが、重要なポイントです。それは、Decoratorパターンは、クラスを作る人が利用するものであり、Proxyパターンは、クラスを使う人が利用するものだということです。

 これまでに何度も言ってきたことですが、オブジェクト指向プログラミングを採用したシステム開発では、開発チーム内に「私はクラスを作る人、貴方はクラスを使う人」という役割分担ができます。同じ工夫であっても、クラスを作る人の視点から見ればDecoratorパターンであり、クラスを使う人の視点から見ればProxyパターンなのです。Proxyパターンの評価もDecoratorパターンと同じく、星5つとさせていただきます。「視点」という感覚を持つのは、プログラマにとって大事なことですよ。

 次回は、CommandパターンとStrategyパターンを紹介します。

矢沢久雄

グレープシティ株式会社(http://www.grapecity.com)アドバイザリースタッフ

表紙ページへ