Tbpgr Blog

Ruby プログラマ tbpgr(てぃーびー) のブログ

RubyでBuilderパターン

概要

GoFデザインパターンのBuilderパターンについて。

Builderパターン

内容

一覧の流れを行うBuilderをDirectorから呼び出す。
一定の手順を必要とするオブジェクトの生成を柔軟に実装することが出来る。

登場人物

Director = 現場監督
Builder = 建築者
ConcreteBuilder = 具体的な建築者

UML


サンプル仕様

任意のプログラム言語のクラスを生成する処理を想定。
言語作成監督の指示により、指定の言語のクラスを作成する。

サンプル登場人物

Director = languageDirector : 言語作成監督
Builder = languageBuilder : 言語作成者
ConcreteBuilder = JavaBuilder : Java作成者
ConcreteBuilder = RubyBuilder : Ruby作成者

UML


サンプルコード

language_builder.rb

# encoding: Shift_JIS
=begin rdoc
= LanguageBuilderクラス
=end
class LanguageBuilder
  attr_accessor :class_name,:field_list,:method_list
  NOT_OVERRRIDE = 'not override error'

  def initialize(class_name, field_list, method_list)
    raise LanguageBuilder::NOT_OVERRRIDE
  end

  def create_class()
    raise LanguageBuilder::NOT_OVERRRIDE
  end

  def create_methods()
    raise LanguageBuilder::NOT_OVERRRIDE
  end

  def create_fields()
    raise LanguageBuilder::NOT_OVERRRIDE
  end
  
  def get_start()
    raise LanguageBuilder::NOT_OVERRRIDE
  end
  
  def get_end()
    raise LanguageBuilder::NOT_OVERRRIDE
  end
end

ruby_builder.rb

# encoding: Shift_JIS
require_relative './language_builder'

=begin rdoc
= RubyBuilderクラス
=end
class RubyBuilder < LanguageBuilder
  def initialize(class_name, field_list, method_list)
    @class_name = class_name
    @field_list = field_list
    @method_list = method_list
  end

  def create_class()
    return "class #{@class_name}"
  end

  def create_fields()
    fields = ""
    @field_list.each {|field|
      fields << "\t" + field['name']
      if field['value'].nil?
        fields << "\n"
      else
        fields << " = \'#{field['value']}\'\n"
      end
    }
    return fields
  end

  def create_methods()
    methods_ = ""
    @method_list.each {|method_|
      methods_ += "\tdef #{method_['name']}("
      if method_['param']
        method_['param'].each {|method_param|
          methods_ += "#{method_param},"
        }
        #右端の1文字を削除すること
        methods_ = methods_.slice(0,methods_.size-1)
      end
      methods_ += ")\n\n\tend\n\n"
    }
    return methods_
  end
  def get_start()
    return ""
  end
  
  def get_end()
    return "end"
  end
end

java_builder.rb

# encoding: Shift_JIS
require_relative './language_builder'

=begin rdoc
= JavaBuilderクラス
=end
class JavaBuilder < LanguageBuilder
  def initialize(class_name, field_list, method_list)
    @class_name = class_name
    @field_list = field_list
    @method_list = method_list
  end

  def create_class()
    return "public class #{@class_name}"
  end

  def create_fields()
    fields = ""
    @field_list.each {|field|
      fields << "\tpublic "
      if field['type'].nil?
        fields << "void"
      else
        fields << field['type']
      end
      fields << " #{field['name']}"
      if field['value'].nil?
        fields << ";\n"
      else
        fields << " = \"#{field['value']}\";\n"
      end
    }
    return fields
  end

  def create_methods()
    methods_ = ""
    @method_list.each {|method_|
      methods_ << "\tpublic "
      if method_['type'].nil?
        methods_ << "void"
      else
        methods_ << method_['type']
      end
      methods_ << " #{method_['name']}("
      if method_['param']
        method_['param'].each {|method_param|
          methods_ << "#{method_param['type']} "
          methods_ << "#{method_param['param']},"
        }
        #右端の1文字を削除すること
        methods_ = methods_.slice(0,methods_.size-1)
      end
      methods_ << ") { \n\n\t}\n\n"
    }
    return methods_
  end

  def get_start()
    return "{"
  end
  
  def get_end()
    return "}"
  end
end

language_director.rb

# encoding: Shift_JIS
require_relative './language_builder'
require_relative './java_builder'
require_relative './ruby_builder'

=begin rdoc
= LanguageDirector生成するFactoryクラス
=end
class LanguageDirector
  @lang
  def initialize(builder)
    @lang = builder
  end
  
  def create_language()
    ret = ""
    ret << @lang.create_class
    ret << @lang.get_start
    ret << @lang.create_fields
    ret << @lang.create_methods
    ret << @lang.get_end
    return ret
  end
    
end

main.rb

require_relative './language_director'
require_relative './language_builder'
require_relative './java_builder'
require_relative './ruby_builder'

puts "■Javaコード生成"
puts "−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−"
class_name = "SampleJavaClass"
method1 = {"name"=>"sampleJavaMethod1", "type"=>"String", "param"=>nil}
method2 = {"name"=>"sampleJavaMethod2", "type"=>nil, "param"=>[{"param" => "param1", "type" => "Map"},{"param" => "param2", "type" => "List"}]}
method_list = [method1,method2]

field1 = {"name"=>"sampleJavaField1", "type"=>"int", "value"=>nil}
field2 = {"name"=>"sampleJavaField2", "type"=>"String", "value"=>"default"}
field_list = [field1,field2]
lang = JavaBuilder.new(class_name, field_list, method_list)
director = LanguageDirector.new(lang)
puts director.create_language()

puts "■Rubyコード生成"
puts "−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−"

class_name = "SampleRubyClass"
method1 = {"name"=>"sample_ruby_method1", "type"=>nil, "param"=>nil}
method2 = {"name"=>"sample_rava_method2", "type"=>nil, "param"=>["param1","param2"]}
method_list = [method1,method2]

field1 = {"name"=>"sample_ruby_field1", "type"=>nil, "value"=>nil}
field2 = {"name"=>"sample_ruby_field2", "type"=>nil, "value"=>"default"}
field_list = [field1,field2]
lang = RubyBuilder.new(class_name, field_list, method_list)
director = LanguageDirector.new(lang)
puts director.create_language()
出力

Javaコード生成
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

public class SampleJavaClass{	public int sampleJavaField1;
	public String sampleJavaField2 = "default";
	public String sampleJavaMethod1() { 

	}

	public void sampleJavaMethod2(Map param1,List param2) { 

	}

}

Rubyコード生成
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

class SampleRubyClass	sample_ruby_field1
	sample_ruby_field2 = 'default'
	def sample_ruby_method1()

	end

	def sample_rava_method2(param1,param2)

	end

end