LoginSignup
4
4

More than 5 years have passed since last update.

Abstruct Factorty パターン

Posted at

関連するインスタンス群を生成するための API を集約することによって、複数のモジュール群の再利用を効率化することを目的とする

何をするの?

Clinet クラスが ConcreteFactory クラスに、ConcreteProduct の生成を移譲する

具体例

ファイルの download と、upload を行う処理 (Clientクラス)

abstract_factory.rb
# ファイルを生成して、upload するという流れ
class FileUploader # Client
  def initialize(factory)
    @file_maker = factory.file_maker
    @uploader   = factory.uploader
  end

  def make_flie(items)
    @file = file_maker.make(item)
  end

  def upload
    uploader.upload(@file)
  end
end

class FileUploaderFactory # AbstructFactory
  def file_maker
    raise NotImplementedError
  end

  def uploader
    raise NotImplementedError
  end
end

class CsvFileScpUploderFactory < FileUploaderFactory # ConcreteFactory
  def file_maker
    @file_maker ||= CsvFileMaker.new # ConcreteProduct
  end

  def uploader
    @uploader ||= ScpUploder.new # ConcreteProduct
  end
end

class HttpFileFtpUploderFactory < FileUploaderFactory # ConcreteFactory
  def file_maker
    @file_maker ||= HttpFileMaker.new # ConcreteProduct
  end

  def uploader
    @uploader ||= FtpUploder.new  # ConcreteProduct
  end
end

# FileUploader は、どの ConcreteProduct を使って処理を行うかを、AbstructFactory のサブクラスに任せている
file_uploader = FileUploader.new(CsvFileScpUploderFactory.new) # CSV を SCP で upload
file_uploader.make_flie(%w[abc def])
file_uploader.upload

file_uploader = FileUploader.new(HttpFileFtpUploderFactory.new) # HTTP を FTP で upload
file_uploader.make_flie(%w[abc def])
file_uploader.upload

# 新しい処理が必要になったら、ConcreteFactory、ConcreteProduct を増やせばよいだけ

いちいち、ConcreteFactory を作るのめんどくない?

上記のような例の場合は、FileUploader のコンストラクタで動的に ConcreteProduct を指定するやり方でも良いと思う

file_uploader.rb
class FileUploader
  def initialize(file_maker_name, uploader_name)
    @file_maker = Object.const_get("#{file_maker_name.to_s.capitalize}FileMaker").new
    @uploader   = Object.const_get("#{file_maker_name.to_s.capitalize}Uploader").new
  end
...
FileUploader.new(:http, :ftp) # HTTP を FTP で upload
FileUploader.new(:csv, :scp)  # CSV を SCP で upload

ただし、AbstructFactory の目的に 矛盾の無い ContcreteProduct の組み合わせの生成 というのもあるので、
ContcreteProduct の組み合わせに制限がある場合は、クラスとしてまとめてしまった方がより安全に運用できる

  • 例えば、HTTPの場合、絶対にFTPしか許されない。とか

Abstruct Factorty パターンと、Factorty Method パターンの違い

実際に処理を行うインスタンスの生成方法が異なる

  • Abstruct Factorty パターン : インスタンスの生成をファクトリオブジェクトに委譲
  • Factory Method パターン : インスタンスの生成をサブクラスに委譲

参考

4
4
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
4
4