Java.use(better);

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


Episode#02

Strategy パターンの隘路 -- GoF を反面教師に


《関連記事》

《目的》

Java の欠陥を補うために「GoFデザインパターン」を適用したときの隘路を確認した後で「クロージャー」を導入して問題を解決するなど、洗練された OOP を促進する術を紹介します。

《動機》

Jython を導入したのは、Java の生産性の低さ(クロージャーを持たないなど)に業を煮やしたからです。Java プログラマーにとって、GoF の著書は福音をもたらします。が同時に「Java の脆弱さ」も露呈しました。というのも、本格的な OOP 言語を知るプログラマーにとって、いくつかのデザインパターンは、無用の長物だからです。Jython/Scala を導入すると、Java が閉ざした門戸を開放して、洗練された OOP の醍醐味を堪能できます。

GoF を反面教師に

いくつかのパターンは、プログラミング言語の欠陥を補う手段を提供します。本格的なオブジェクト指向/関数型プログラミング言語を利用したいプログラマーにとって、Java の脆弱さは憂慮に堪えません。Jython/Scala などは「Java で鎖された機能を復活させる」のに役立ちます。

Design Pattern が出版された当時(1994年)を考えると、C++ を基準にしたのは順当でしょう。しかし、見方を変えるとそれは、C++ の「脆弱さ」を物語っています。Java(1995年)も、その例に漏れません。そこで、8つのパターンを選んで、Smalltalk-80 では、これらは無用の長物でしかないことを例示しました(1995年)。また、Jython/Scala では「パターンに頼らなくてもJava で鎖された機能を復活できます。

GoF の隘路:卑近な例をあげると

Java の「脆弱さ」を物語る事例には、枚挙に暇がありません。その典型が、Singleton パターンです。Scala では、object を導入するだけで、冗長な Java のコードを削除できます。つまり、Singleton パターンのエッセンスはすでに、言語仕様に盛り込まれています。

たとえば、次の事例では、マルチスレッドの環境下で、オブジェクトの妥当性を保証します。

    var singleton1 = Singleton
    singleton1.display
    singleton1.votes += 1
    singleton1 = null

    val t = new Thread {
      override def run {
        var singleton2 = Singleton
        singleton2.display
        singleton2.votes += 1
        singleton2 = null
      }
    }
    t.start()
    t.join()

    var singleton3 = Singleton
    singleton3.display

これをマルチスレッドで実行すると、

Collector: 8789796, Votes: 0
Collector: 8789796, Votes: 1
Collector: 8789796, Votes: 2

有効な得票数を計上できるのが分ります。Scala でこれを実現すると、

object Singleton {
  var votes = 0
  def display {
    println("Collector: %s, Votes: %d" format (hashCode,votes))
  }
}

object を宣言するだけなので、意図的にバグを盛り込む余地がありません。ところが、同じことを Java で実現すると、

class Singleton {
  public static volatile Singleton instance = null;
  private Singleton() {}
  public static Singleton getInstance() {
    if (instance == null) {
      synchronized (Singleton.class) {
        if (instance == null)
          instance = new Singleton();
      }
    }
    return instance;
  }
  public int votes = 0;
  public void display() {
    System.out.println(String.format(
      "Collector: %s, Votes: %d", hashCode(), votes));
  }
}

これだけの「冗長なコード」が必要になり、バグの温床になりかねません。

 ↑ TOP

》作業中です《

update*13/01/07 4:14:06

♪ 龍膽車(りんどうぐるま)



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