Compositeパターン 全体から部分を組立てる
オブジェクト指向でソフトウェアを作ることは、シンプルなオブジェクトを組み合わせて、より複雑なオブジェクトを作るプロセスにほかならない。そうしてできたオブジェクトはより高度なオブジェクトを構築するために使うことができる。このプロセスを経ると、たいていは幾つかの非常に高機能なオブジェクトができる。そしてそれらのオブジェクトは、そのオブジェクトを組み立てるために利用したコンポーネントとは似ても似つかないものになる。
しかし、場合によっては構成するコンポーネントと同じように見え、振る舞うオブジェクトが必要になるときもある。
GoFは、「全体が部分のように振る舞う」という状況を表すパターンをCompositeパターンと呼んでいる。
このパターンは、以下2つのケースで利用できる。
・階層構造やツリー構造のオブジェクトを作りたい時
・ツリーを利用するコードが単純なオブジェクトを扱っているのか、それとも複雑なオブジェクトを扱っているのかを考えさせたくない時
Compositeパターンを作るには3つの部品を使う。
1,全てのオブジェクトの共通のインタフェースまたは基底クラス =>コンポーネント
2,葉クラス
3,コンポジットクラス
# ケーキを作るクラス # コンポジットクラスがたくさんあることが想定されるので、 # 小タスク管理の詳細は、Compositeという基底クラスを作って管理する # コンポーネントクラス class Task attr_reader :name def initialize(name) @name = name end def get_time_required end end # 小タスクの管理をするコンポジットクラス class CompositeTask < Task def initialize(name) super(name) @sub_tasks = [] end def add_sub_task(task) @sub_tasks << task end def remove_sub_task(task) @sub_tasks.delete(task) end def get_time_required time = 0.0 @sub_tasks.each {|task| time += task.get_time_required} time end end # 葉クラス # 小麦粉と砂糖を加えるタスク class AddDryIngrediendsTask < Task def initialize super('Add dry ingredients') end def get_time_required 1.0 # 所要時間1分 end end # 葉クラス # 混ぜるタスク class MixTask < Task def initialize super('Mix that batter up') end def get_time_required 3.0 #所要時間3分 end end # 葉クラス # 水を追加するタスク class AddLiquidsTask < Task def initialize super('Add liquid') end def get_time_required 2.0 end end # コンポジットクラス # バターを作る class MakeBatterTask < CompositeTask def initialize super('Make batter') add_sub_task(AddDryIngrediendsTask.new) add_sub_task(AddLiquidsTask.new) add_sub_task(MixTask.new) end end #super: superは現在のメソッドがオーバーライドしているメソッドを呼び出す adit = AddDryIngrediendsTask.new puts adit.get_time_required # => 1.0 mt = MixTask.new puts mt.get_time_required # => 3.0 alt = AddLiquidsTask.new puts alt.get_time_required # => 2.0 mbt = MakeBatterTask.new puts mbt.get_time_required # => 6.0
・コンポーネントクラス: Task
・葉クラス: AddDryIngrediendsTask, MixTask, AddLiquidsTask
・コンポジットクラス: Composite, MakeBatterTask
出力結果を見ると、コンポジットクラスであるMakeBatterTaskクラスは、他の単純なタスクと同じように見えるけれど、実際には3つのタスクから構成されている。これがCompositeパターンの一例。