Java.use(better);
Java.use(better);
Episode#02
Strategy パターンの隘路 -- GoF を反面教師に
《関連記事》
Strategy パターンを導入すると、開発者(プログラマー)は、利用者(プログラマー)には影響を与えずに、その問題解決に必要な戦略を自由に選択できます。たとえば、文字列を連結するのに、演算子 + を利用する戦略と、バッファー StringBuffer を利用する戦略が考えられます。「情報隠蔽の原則」に従うなら、利用者はその違いを知らず、また知る必要もありません。すると、
def data = "ABCDEFGH".toList val contextA = new Context( data => { var s = "" data foreach { s += _ } s }) println("A: %s" format (contextA strategy data)) val contextB = new Context( data => { val buf = new StringBuffer data foreach { buf.append(_) } buf.toString }) println("B: %s" format (contextB strategy data))
利用者は、2つの戦略 contextA/contextB の違いを意識せずに、同じメソッド呼び出し strategy data を再利用できます。開発者は、2つの戦略の違いを「クロージャー内に隠蔽」できます。注目に値するのは、利用者/開発者の違いを示すコードの断片がすべて、ここに集約されていることです。他に冗長な仕掛は不要です。
Scala でこれを実現するには、
class Context(val strategy: List[Char] => String)
class を宣言するだけなので、意図的にバグを盛り込む余地がありません。ところが、Java で同じことを実現すると、
class Context { private Strategy strategy; Context(Strategy strategy) { this.strategy = strategy; }String execute(char[] data) { return strategy.execute(data); }}
これだけの「冗長なコード」が必要になり、バグの温床になりかねません。
interface Strategy { public String execute(char data); } class ConcreteStrategyA implements Strategy { public String execute(char data) {String s = ""; for (char c: data) { s += c; } return s;} } class ConcreteStrategyB implements Strategy { public String execute(char[] data) {StringBuffer buf = new StringBuffer(); for (char c: data) { buf.append(c); } return buf.toString();} }
↑ TOP
》作業中です《update*13/01/08 0:13:24