Tbpgr Blog

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

RubyでTemplateメソッドパターンとFactoryメソッドパターン

概要

GoFデザインパターンのTemplateメソッドパターンとFactoryメソッドパターンについて。
FactoryメソッドパターンはTemplateメソッドパターンを利用しているので
Factoryメソッドパターンのサンプル説明を持って、Templateメソッドパターンの説明を兼ねることにします。

Templateメソッドパターン

内容

処理の流れをAbstractの基底クラスで行い、具体的な処理を継承側で行う。
大筋の処理が同じで、個別の処理が異なるサブクラスを多数作成する際などに有効。

登場人物

AbstractClass = テンプレート部分を定義する抽象クラス
ConcreteClass = 個別の実装を受け持つ継承クラス

実例

JUnitがTemplateメソッドパターンを利用してます。
基底クラスでsetup(前処理)、testXXX、tearDown(後処理)の処理の流れを定義して、
実際にテストを実装する側はこれを継承して具体的な処理を追加します。

UML


Factoryメソッドパターン

インスタンスの生成を工場=Factoryに任せるパターン。
クラスの生成を隠蔽することで結合度を下げることができます。

登場人物

AbstractFactoryClass = Factoryの共通したテンプレートを定義する抽象クラス
ConcreteFactoryClass = Factoryの個別実装を受け持つ継承クラス
AbstractProduct = Productのインターフェースとテンプレートを定義する抽象クラス
ConcreteProduct = Productの個別実装を受け持つ

UML


サンプル仕様

AbstractFactoryClass役 = TagFactory:HTMLのタグを生成する
ConcreteFactoryClass = DivTagFactory:HTMLのDIVタグを生成する
ConcreteFactoryClass = SpanTagFactory:HTMLのSPANタグを生成する
AbstractProduct = Tag:インターフェースとテンプレートを定義する抽象クラス
ConcreteProduct = Div:Divタグ個別実装を受け持つ
ConcreteProduct = Span:SpanTagの個別実装を受け持つ
main = 動作確認用メイン処理

UML


サンプルコード

tag_factory.rb

# encoding: Shift_JIS
require_relative './tag'

=begin rdoc
= Tagを生成するFactoryクラス
=end
class TagFactory
  @tag

  protected
  def setTag()
    raise 'error'
  end
  
  public
  def getTag()
    setTag
    return @tag
  end
  
end

div_tag_factory.rb

# encoding: Shift_JIS
require_relative './tag_factory'
require_relative './tag'
require_relative './div'

=begin rdoc
= DivTagを生成するFactoryクラス
=end
class DivTagFactory < TagFactory
  protected
  def setTag()
    @tag = Div.new
  end
end

span_tag_factory.rb

# encoding: Shift_JIS
require_relative './tag_factory'
require_relative './tag'
require_relative './span'

=begin rdoc
= SpanTagを生成するFactoryクラス
=end
class SpanTagFactory < TagFactory
  protected
  def setTag()
    @tag = Span.new
  end
end

tag.rb

# encoding: Shift_JIS
=begin rdoc
= Tagクラス
=end
class Tag
  @tag_name = ""
  attr_accessor :inner_text

  protected
  def setTag()
    raise 'error'
  end

  public
  def getOuterHtml()
    setTag
    return "<#{@tag_name}>#{@inner_text}</#{@tag_name}>"
  end
end

div.rb

# encoding: Shift_JIS
require_relative './tag'

=begin rdoc
= Divクラス
=end
class Div < Tag
  protected
  def setTag()
    @tag_name = "div"
  end
end

span.rb

# encoding: Shift_JIS
require_relative './tag'

=begin rdoc
= Spanクラス
=end
class Span < Tag
  protected
  def setTag()
    @tag_name = "span"
  end
end

main.rb

require_relative './tag_factory'
require_relative './div_tag_factory'
require_relative './span_tag_factory'
require_relative './tag'
require_relative './div'
require_relative './span'

div_factory = DivTagFactory.new
div = div_factory.getTag
div.inner_text = "divの中身"
puts div.getOuterHtml

span_factory = SpanTagFactory.new
span = span_factory.getTag
span.inner_text = "spanの中身"
puts span.getOuterHtml
出力
<div>divの中身</div>
<span>spanの中身</span>