概要
Composite Pattern
詳細
Composite Patternは、全体が部分のように振る舞えるようにするパターンです。
階層やツリー構造を作り、利用者からは全体なのかツリーなのか意識しないで使えるように
設計したい場合に利用します。
サンプル仕様
マインドマップを表すクラスを作成します。
子を持たない要素を葉 : Leaf
子を持つ要素を根 : Root
とします。
葉、および根は名称を持ちます。
根は複数の葉を持つことができます。
本当はもっといろんな要素があるのですが、今回はシンプルに以上の要件にします。
Compositeパターンサンプル
require 'tbpgr_utils' require 'attributes_initializable' require 'pp' module Mindmap class Leaf include AttributesInitializable attr_reader_init :name end class Root < Leaf include Enumerable attr_reader :leaves def initialize(name, leaves = []) super(name) @leaves = leaves end def << (leaf) @leaves << leaf end def each @leaves.each { |leaf| yield(leaf) } end end end root = Mindmap::Root.new(name: "デザインパターン") gof = Mindmap::Root.new(name: "GoF") %w{エーリヒ・ガンマ リチャード・ヘルム ラルフ・ジョンソン ジョン・ブリシディース}.each do |member| gof << Mindmap::Leaf.new(name: member) end categories = Mindmap::Root.new(name: "パターン分類") %w{生成 構造 振る舞い}.each { |category|categories << Mindmap::Leaf.new(name: category) } root << gof root << categories def show_maps(leaves, nested_level) tabs = "\t"*nested_level puts "#{tabs}#{leaves.name}" leaves.each do |leaf| if leaf.is_a? Mindmap::Root show_maps(leaf, nested_level + 1) else tabs = "\t"*(nested_level + 1) puts "#{tabs}#{leaf.name}" end end end show_maps(root, 0) __END__ AttributesInitializableはtbpgr_utils gemの機能です。 詳しくは https://github.com/tbpgr/tbpgr_utils を参照。
出力
デザインパターン GoF エーリヒ・ガンマ リチャード・ヘルム ラルフ・ジョンソン ジョン・ブリシディース パターン分類 生成 構造 振る舞い
Compositeパターンサンプル(変形)
最初のサンプルだと、再帰の処理にif文が入ってしまっています。
なので葉にeachメソッドを定義して空配列を返却することで、
根がeachで空配列を返却するのと同じ動作をさせることにします。
これにより、再帰に分岐がなくなります。
require 'attributes_initializable' require 'pp' module Mindmap class Leaf include AttributesInitializable attr_reader_init :name def each [] end end class Root < Leaf include Enumerable attr_reader :leaves def initialize(name, leaves = []) super(name) @leaves = leaves end def << (leaf) @leaves << leaf end def each @leaves.each { |leaf| yield(leaf) } end end end root = Mindmap::Root.new(name: "デザインパターン") gof = Mindmap::Root.new(name: "GoF") %w{エーリヒ・ガンマ リチャード・ヘルム ラルフ・ジョンソン ジョン・ブリシディース}.each do |member| gof << Mindmap::Leaf.new(name: member) end categories = Mindmap::Root.new(name: "パターン分類") %w{生成 構造 振る舞い}.each { |category|categories << Mindmap::Leaf.new(name: category) } root << gof root << categories def show_maps(leaves, nested_level) tabs = "\t"*nested_level puts "#{tabs}#{leaves.name}" leaves.each { |leaf|show_maps(leaf, nested_level + 1) } end show_maps(root, 0) __END__ AttributesInitializableはtbpgr_utils gemの機能です。 詳しくは https://github.com/tbpgr/tbpgr_utils を参照。
出力
デザインパターン GoF エーリヒ・ガンマ リチャード・ヘルム ラルフ・ジョンソン ジョン・ブリシディース パターン分類 生成 構造 振る舞い