Java.use(better);

前の記事次の記事
Java.use(better);


Episode#04

Command パターンの効能 -- if と別れる50の方法



《関連記事》

《目的》

OOP の障害となる「if/switch 文」の隘路を確認した後で、Command パターンを適用して「ポリモフィズム」を促進する術を紹介します。

《動機》

Java は、純粋な OOP を目指すのではなく、SP との中庸を選択しました。そのため、switch 文が混在すると、すべてを OOP の枠組みで統一的に扱うのが困難です。また、複雑な条件分岐を適切に管理するのは面倒なだけでなく、コードが複雑で見通しも悪くなるので、避けたいものです。そこで、match 式を利用すると、異なる機能を持つコンポーネント(ボタン、メニュー、リスト、表、ツリーなど)のすべてに有効な、ポリモフィズムを実現できます。すると、要求仕様の変更にも柔軟に対処できるので、ソフトウエア開発の能率が上がります。

Scala で導入された「match 式」は、ともすると、古典的な switch 文と同列に比較されがちです。しかし、プログラミングの立場からすると、これらには雲泥の開きがあります。古典的な switch 文は、SP の三本柱のひとつ「分岐」構造を支援します。match 式は、OOP の三本柱のひとつ「ポリモフィズム」を支援します。また、match 式の特性を利用して「パターンマッチング」を実現できます。これにより、オブジェクト指向プログラミングと関数型プログラミングとの融合を図り、プログラミングの能率を劇的に向上できます。

■ 構造化プログラミングの隘路

GUI コンポーネントを扱う典型的な事例で話を進めます。以下の事例では、

ボタン[Click me!]をクリックするたびにカウンターの値がひとつずつ増えて、その値がウインドーのタイトルに表示されます。メニュー項目[Open...]を選択すると、ファイルを選択する FileDialog が現れます。メニュー項目[Quit]を選択すると、アプリケーションが終了します。

 ̄構造化プログラミングにおける三種の神器(連接/選択/反復)の中から、この問題解決に必要なのは何でしょう。それは、if/switch などの「条件分岐」です。そこでは、任意の条件式を満たすときだけ、処理を実行するという流れに沿って、コンポーネントアルゴリズムが確定します。

 ̄どの GUI コンポーネントを扱うときも、イベント処理が必要です。たとえば、

// -------------------------------------- before
  public void actionPerformed(ActionEvent e)   {
    Object obj = e.getSource();
    if (obj instanceof JButton) {
      *1 {
        *2 {
        ((QuitMenu)obj).execute();
      }
    }
  }

外側の if 文では、演算子 instanceof を利用して、コンポーネントの種別 JButton/JMenuItem を行います。内側の if 文では、文字列を比較 equals して、コンポーネントの特定を行います。多重の if 文は、コードが複雑で見通しも悪くなるだけでなく、バグの温床になりがちです。

 ̄ここで注目に値するのは「個別の処理に呼応する、多重の if 文」です。複雑な条件分岐を管理するのは面倒なだけでなく、コードが煩雑で見通しも悪くなります。また、要求仕様の変更(新たな処理の追加)には柔軟に対処できないので、ソフトウエア開発の能率も悪くなります。この問題を解決する、何かうまい仕掛はないものでしょうか。

 ↑ TOP

》作業中です《

update*13/01/16 19:16:14

♪ 巣籠(すごもり)



出典 ☞ http://shimayu.co.jp/modules/myalbum/photo.php?lid=88

*1:CountButton)obj).execute(); } if (obj instanceof JMenuItem) { String s = ((JMenuItem)obj).getText(); if (s.equals("Open..."

*2:OpenMenu)obj).execute(); } if (s.equals("Quit"