Java.use(better);
《目的》
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
》作業中です《♪ 龍膽車(りんどうぐるま)