関連するインスタンス群を生成するための 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 パターン : インスタンスの生成をサブクラスに委譲