16
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Factory Method パターン

Last updated at Posted at 2014-07-24

Factory Method パターンは、他のクラスのコンストラクタをサブクラスで上書き可能な自分のメソッドに置き換えることで、 アプリケーションに特化したオブジェクトの生成をサブクラスに追い出し、クラスの再利用性を高めることを目的とする。

ざっくり言うと?

インスタンスの生成部分を、サブクラスにお任せするパターン

使い道

Template Method パターン のインスタンスを使って、何かしらの処理を行う class をキレイに実装する

実装例

StringLister#display の内容を画面に出力する StringListerViewer を作る

factory_method.rb

# Creator に相当
class StringListerViewer
  attr_reader :items
  def initialize(items)
    @items = items
  end

  def display # anOpreation に相当
    puts string_lister(items).display
  end

  def string_lister(items) # factoryMethod に相当
    raise NotImplementedError
  end
end

# ConcreteCreator に相当
class TextStringListerViewer < StringListerViewer
  def string_lister(items)
    # ConcreteProduct に相当
    TextStringLister.new(items)
  end
end

# ConcreteCreator に相当
class HtmlStringListerViewer < StringListerViewer
  def string_lister(items)
    # ConcreteProduct に相当
    HtmlStringLister.new(items)
  end
end

items = %w[abc def ghi]
HtmlStringListerViewer.new(items).display
# <html><body>
# <div>abc</div>
# <div>def</div>
# <div>ghi</div>
# </body></html>

TextStringListerViewer.new(items).display
# abc
# def
# ghi
  • StringListerViewer クラス → anOparation を実装
  • StringListerViewer のサブクラス → factoryMethod を実装
  • インスタンスの生成を、各サブクラスに投げる
    • StringListerViewer の結合度が下がる
    • StringListerViewer のサブクラスでは、インスタンスの生成を実装するだけで済むようになる

ConcreteCreator を作らないで、動的に Product のサブクラスを生成してみる

Object.const_get を使って、文字列からクラスを取得する
大量に Product のサブクラスがある時に、いちいち ConcreteCreator クラスを作らないので楽

factory_method.rb
class StringListerViewer
  attr_reader :items, :type
  def initialize(items, type)
    @items = items
    @type = type
  end

  def string_lister(items)
    Object.const_get("#{type.to_s.capitalize}StringLister").new(items)
  end

  def display
    puts string_lister(items).display
  end
end

items = %w[abc def gih]
StringListerViewer2.new(items, :text).display
StringListerViewer2.new(items, :html).display

Factory パターンのその他の利点

コンストラクタがシンプルになる

  • 複雑な処理はインスタンス生成後に、別メソッドとして呼び出す事ができる
  • 複雑な事前処理を分離することで、実装がシンプルになったりテストが書きやすくなる
  • 事前処理が別メソッドでも、生成はファクトリメソッドに一任されているから、事前処理の呼び出しもれが無い

参考

Abstruct Factorty パターン に続く

16
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?