GoFのデザインパターン(Design Pattern)の一つ、ファクトリメソッド(Factory Method)をRubyのサンプルコードで紹介します。
ファクトリメソッドは、インスタンスの生成をサブクラスに任せるパターンです。インスタンスの生成部分を切り離すことで、結合度を下げて追加・変更・保守を容易にします。
ソースコードを使ったファクトリメソッドの説明
ファクトリメソッドをソースコードを使って説明します。
ここではサックスとサックスを作る工場を例に考えます。
サックスを表すSaxophoneクラスは、音を鳴らす(play)メソッドを持っている 楽器工場を表すInstrumentFactoryクラスは * コンストラクタの引数で楽器の数を受け取る * 楽器を出荷するメソッド「ship_out」を持つ
を満たすコードを書いていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
上のプログラムを呼び出してみます。
1 2 3 | |
この結果は次のようになります。
1 2 3 | |
ここで、トランペット(Trumpet)のモデルを追加することになりました。 インターフェイスはサックスと全く同じものとします。
1 2 3 4 5 6 7 8 9 10 | |
先ほど作ったInstrumentFactoryモデルをもう一度確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
トランペットを追加する場合にInstrumentFactoryモデルで問題になるのは、コンストラクタ(initialize)でサックスを作っている点です。
1
| |
そこで、InstrumentFacotory内でサックスを生成している部分をサブクラス(SaxophoneFacotory)に切り出します。また、トランペットを生成するTrumpetFactoryクラスを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
InstrumentFactoryはnew_instrument(楽器の生成)の処理を抽象化しています。
(抽象化は、言い換えると「異なるものをひとまとめにする」ということです)
上のプログラムの結果を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 | |
上の通り、サックス/トランペットを作成、音を奏でる事ができました。
この例のようにクラスの選択をサブクラスに任せることを「FactoryMethod」と呼びます。
ファクトリメソッドは次の3つで構成されています。
Creator: ConcreteFactoryの共通部分の処理を行う(この例ではInstrumentFactory) ConcreteCreator: 実際にオブジェクトの生成を行う(この例ではSaxophoneFactory, TrumpetFactoryクラス) Product: ConcreteFactoryによって生成される側のオブジェクト(この例では、Saxophone,Trumpetクラス)
ファクトリメソッドは生成するProductへの依存度を下げて、生成部分を切り離すことで変更や追加、保守を容易にするメリットがあります。
このサンプルソースはGitHubにも置いているので良かったら使って下さい。
Special Thanks
@ponta_さんにファクトリメソッドについて沢山アドバイスをいただきました。本当にありがとうございました!
サルでもわかる 逆引きデザインパターン 第2章 逆引きカタログ ロジック編 Factory/Factory Method(ファクトリ/ファクトリメソッド)
RubyでTemplateメソッドパターンとFactoryメソッドパターン
Amazon.co.jp: Rubyによるデザインパターン: Russ Olsen, ラス・オルセン, 小林 健一, 菅野 裕, 吉野 雅人, 山岸 夢人, 小島 努: 本
変更来歴
12/10 09:00 GitHubへのサンプルソースの設置。導入文の修正
12/10 22:10 ファクトリの間違いを修正、Factory MethodとAbstract Factoryに分割
12/11 00:00 書籍へのリンクをAmazon アフィリエイトに変更
06/21 18:50 Ruby2.0.0対応、読みづらい部分を修正
08/09 22:15 例題コードの説明が不適切だったため、書き直し