結局はDRY原則もOCPも「原則」に過ぎず,状況に応じて適切に選択しなければならないということなのでしょう。再利用する予定がない,あるいは将来機能拡張する予定がないコードにむりやりデザイン・パターンを適用するのは望ましくないでしょう。デザイン・パターンを適用する際には判断が必要です。
http://itpro.nikkeibp.co.jp/article/COLUMN/20070611/274310/?ST=oss&P=3
誌面の関係からデザイン・パターンのうちのごく一部しか検証しませんでしたが,世の中にあるデザイン・パターンの多くは将来の変更に対処するためOCPに従うことができるように設計されています。
http://itpro.nikkeibp.co.jp/article/COLUMN/20070611/274310/?ST=oss&P=4
Singletonパターン
singletonライブラリを使えば,任意のクラスにSingletonモジュールをincludeすることで,そのクラスをSingletonパターンの対象にできます。
Objectクラスのオブジェクトを作って,そのオブジェクトに(引用者註:特異メソッドを用いて)必要な機能を追加するという方法も使えます。
Proxyパターン
Iteratorパターン
Enumerableモジュールが提供するメソッドの多くは,Iteratorパターンを実現している
クロージャのない言語では,内部イテレータは現実的ではありません。
Rubyでは内部イテレータが好まれますが,外部イテレータを使えないわけではありません。
内部イテレータの欠点は,同時並行の繰り返しができないため,2つのコレクションの要素を順に比較するような処理を書けないことです。
外部イテレータの問題は,イテレータ(カーソル)オブジェクトがコレクション・オブジェクトの内部情報を参照する必要があるため,カプセル化が破れてしまう点です。
Prototypeパターン
Prototypeパターンは実は単なるデザイン・パターンというよりも,1つのプログラミング・パラダイムと言った方がふさわしいものです。
コピーしたオブジェクトに動的にメソッドを追加していくプロトタイプ・プログラミングは静的言語では不可能
JavaScriptのオブジェクト指向機能はプロトタイプ・ベース
# ひな型オブジェクトを用意する object = Object.new # Objectをコピーする dog = object.clone # ひな型dogにsitというメソッドを教える def dog.sit print "I'm sitting.\n" end # dogは犬なのでsitできる dog.sit # ひな型dogから新しいmyDogを作る myDog = dog.clone
Template Methodパターン
オブジェクト指向プログラミングでは,継承を用いて一般的に使われている技法です。
細部を隠したメソッドを呼び出すことで抽象化したアルゴリズムを記述する,そして,細部はサブクラスで提供するのがTemplate Methodパターンです。
Template Methodパターンを用いて,デバッグ出力メソッドpを記述するなら,次のようになるでしょう。意外なほど簡単です。def p(obj) puts obj.inspect endRubyのクラス・ライブラリでTemplate Methodパターンを最も活用している部分は,EnumerableモジュールとComparableモジュールでしょう。
Template MethodパターンはOCP(引用者註:オープン・クローズ原則)を満たす基本的な手段です。Template Methodパターンは継承の利用方法であり,基本的には抽象クラスを作成しているに過ぎないからです。
Observerパターン
Observerパターンは「あるオブジェクトが状態を変えたときに,それに依存するすべてのオブジェクトに自動的にそのことが知らされ,また,それらが更新されるようにオブジェクト間に一対多の依存関係を定義する」パターンです。
Observerパターンを構成するのは,Observer(監視者)と呼ばれる変更の通知を受けるオブジェクトと,Subject(対象)またはObservable(被監視者)と呼ばれる変更を通知するオブジェクトの2つです。
RubyではObserverパターンを簡単に実現するためにその名もobserverというライブラリが提供されています。
実際の更新通知は単にchangedメソッドを呼んで更新フラグをセットしてから,notify_observersメソッドで監視に通知を行っています。
Observerパターンを使うことで相互依存性が劇的に下がっている簡単に機能を追加・変更できることから,このデザイン・パターンは変更に対して「開いている」と考えられます。また,修正に対して「閉じている」。ObserverパターンがOCPを満たしていることが分かりました。
Strategyパターン
Strategyパターンは,変化しやすい処理を独立したオブジェクトにまとめてしまい,交換可能にするためのものです。使い方としては,変化しやすい処理をサブクラスに任せてしまうTemplate Methodパターンに似ています。
Strategyパターンを使った場合,アルゴリズムをカプセル化したStrategyオブジェクトを差し替えるだけで機能を追加・変更できます。Strategyパターンは拡張に対してオープンであると言えます。機能を拡張・変更してもStrategyパターンを利用する側の変更は必要ありません。Strategyパターンは変更に対してクローズであるということになります。よってStrategyパターンはOCPを見事に満たしていることが分かりました。
参考
実は,OCPとデザイン・パターンを組み合わせるというのは,私のオリジナルのアイディアではありません。私の知る限り,国内でこの2つを組み合わせて解説を行ったのは,石井勝氏です。石井さんによる解説はWebページから読むことができます。
http://itpro.nikkeibp.co.jp/article/COLUMN/20070611/274310/?ST=oss&P=4