GoFのデザインパターン(Design Pattern)のコンポジット(Composite
)のRubyコードを使った紹介記事です。
コンポジットとは?
「全体-部分」(個別のオブジェクトと合成したオブジェクト)を同一のものとして捉えることで、再帰的な構造をクラスで表現することをCompositeデザインパターンと呼びます。「全体-部分」は同じインターフェイスを継承します。
コンポジットは次の3つの要素によって構成されます。
コンポーネント(Component):すべてのオブジェクトの基底となるクラス リーフ(Leaf):プロセスの単純な構成要素、再帰しない コンポジット(Composite):コンポーネントの一つでサブコンポーネントで構成
例としては、ディレクトリとフォルダを同様のコンポーネントとして扱うことで、削除処理などを再帰的に行えるようにできることが挙げられます。
ちなみに「再帰」とは、ある処理の中で再びその手続きを呼び出すことです。
コンポジットのメリット
ファイルシステムなどの木構造を伴う再帰的なデータ構造を表現できる 階層構造で表現されるオブジェクトの取扱いを楽にする
ソースコード
ここではファイルシステムのモデルを使ってCompositeデザインパターンを説明します。
FileEntryクラス(Leaf):ファイルを表す DirEntryクラス(Composite):ディレクトリを表す Entryクラス(Component):FileEntry, DirEntryクラスの共通メソッドを規定
まずFileEntryクラス, DirEntryクラスの共通メソッドを規定するEntryクラスです。Componentにあたります。メソッドの実装はFileEntry/DirEntryクラスが個別に持っています。
1 2 3 4 5 6 7 8 9 10 11 | |
次にファイルを表すFileEntryクラスです。ファイルはその下にファイルを持つことができない、つまり再帰できないのでCompositeデザインパターンのLeafにあたります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
最後がディレクトリを表すDirEntryクラスです。ディレクトリはその下にファイルを持つことができる、つまり再帰できるのでCompositeデザインパターンのCompositeにあたります。このクラスは独自のクラスとして、ファイルを追加する#addメソッドを持っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
コーディングは以上です。結果を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
ディレクトリの中にディレクトリ/ファイルを追加できて、#ls_entryメソッド、#removeメソッドで同一のものとみなして処理できていることがわかります。
(再帰的にメソッドを呼び出せていることがわかります)
このサンプルソースはGitHubにも置いています。
コンポジットパターンの注意点
コンポジットパターンでは、コンポジット(Composite)が任意の深さのツリーを作れるようにしておくことが重要となります。
Special Thanks
Amazon.co.jp: Rubyによるデザインパターン: Russ Olsen, ラス・オルセン, 小林 健一, 菅野 裕, 吉野 雅人, 山岸 夢人, 小島 努: 本
変更来歴
12/10 09:00 GitHubへのサンプルソースの設置。導入文の修正
12/11 00:00 書籍へのリンクをAmazon アフィリエイトに変更
12/15 10:35 ソースコードへの説明を追加
06/20 18:00 Ruby2.0.0対応、読みづらい部分を修正