【ITニュース解説】🧠 Desmitificando el Patrón Factory Method con un Toque Manabita
2025年09月13日に「Dev.to」が公開したITニュース「🧠 Desmitificando el Patrón Factory Method con un Toque Manabita」について初心者にもわかりやすく解説しています。
ITニュース概要
ファクトリーメソッドは、作成するオブジェクトの具体的な種類をコードに直接書かず、「工場」に生成を任せるデザインパターンだ。これにより、if-elseの羅列を避け、柔軟に様々なオブジェクトを作り分けられる。システムは共通のインターフェースで処理でき、支払いシステムなどで活用される。
ITニュース解説
Factory Methodは、ソフトウェア開発における「デザインパターン」と呼ばれる、よくある問題に対する解決策の一つだ。特に、プログラムの中で新しい「オブジェクト」(データと機能を持つ実体)を作る方法に関するパターンとして知られている。Factory Methodが目指すのは、どのような種類のオブジェクトを作るかという具体的な決定を、オブジェクトを作るための特別なメソッドに任せることで、コードの柔軟性を高めることである。
想像してみてほしい。あるプログラムの部品が、別の種類のオブジェクトを必要とするが、そのオブジェクトが具体的にどのクラス(設計図)から作られるべきかは、プログラムの実行時の状況や設定によって変わる場合がある。例えば、ユーザーが支払方法を選択したり、システムが特定の環境で動作しているかどうかに応じて、異なる動作をするオブジェクトを使いたい場合などだ。このような時、もしプログラムのあちこちに「もしカード支払いなら、CardPaymentクラスからオブジェクトを作る」「もしGoogle支払いなら、GooglePaymentクラスからオブジェクトを作る」といった具体的な条件分岐(if-elseやswitch文)を書いてしまうと、新しい支払い方法が追加されるたびに、その全ての箇所を修正しなければならなくなる。これは、コードが複雑になり、保守が難しくなる原因となる。
Factory Methodは、この問題を解決する。オブジェクトの生成ロジックを、独立した「ファクトリーメソッド」という特別なメソッドに集約させるのだ。これにより、メインのプログラムは、どの具体的なオブジェクトが作られるかを意識することなく、共通の「インターフェース」(約束事、契約)を通してオブジェクトを要求し、それを利用できる。
具体的な例として、支払いシステムを考えてみよう。
まず、「支払い」という共通の概念を定義する「インターフェース」を作る。これをPaymentインターフェースと呼ぶ。このインターフェースには、全ての支払い方法が必ず持っていなければならない「支払いを行う」という共通の動作(doPayment()メソッド)を約束として定める。これにより、カード支払いも、Google支払いも、PayPal支払いも、すべて「支払いを行う」という同じ呼び出し方で操作できるようになる。
次に、このPaymentインターフェースの約束事に従って、具体的な支払い方法を実現するクラスを作る。これらが「具象製品」と呼ばれるものだ。例えば、CardPaymentクラスはカードでの支払い方法を、GooglePaymentクラスはGoogle Payでの支払い方法を、PaypalPaymentクラスはPayPalでの支払い方法をそれぞれ実装する。これらのクラスは、それぞれ独自のdoPayment()メソッドを持つが、Paymentインターフェースの実装であるため、外から見るとすべて同じ「支払い」として扱える。
そして、Factory Methodの肝となるのが「ファクトリー」クラスである。今回の例ではPaymentFactoryクラスだ。このクラスの主な役割は、プログラムの他の部分から「こういう種類の支払いオブジェクトが欲しい」という要求を受け取り、それに合わせて適切な具象製品クラスのオブジェクトを生成して返すことにある。PaymentFactoryの中にはbuildPaymentという静的なメソッドがあり、このメソッドは「どんな種類の支払いが必要か」を示す情報(TypePaymentという列挙型)を受け取る。buildPaymentメソッドの内部では、switch文を使って、受け取った情報に応じてnew CardPayment()やnew GooglePayment()といった具体的なオブジェクト生成の処理が行われ、生成されたオブジェクトがPaymentインターフェース型として呼び出し元に返される。
これにより、オブジェクトを必要とするプログラムの部品(「クライアント」と呼ぶ)は、具体的な支払い方法のクラス名(CardPaymentなど)を知る必要がなくなる。クライアントは単に「カード支払い用のオブジェクトが欲しい」とPaymentFactoryに依頼するだけだ。例えば、次のように書けばよい。「Payment payment = PaymentFactory.buildPayment(TypePayment.CARD);」。そして、返されたpaymentオブジェクトに対して「payment.doPayment();」と呼び出すと、具体的な支払い方法が何であるかに関わらず、適切な支払いが実行される。
このアプローチの大きな利点は、拡張性の高さと保守のしやすさにある。もし将来的に新しい支払い方法(例えば、Apple Pay)を追加することになったとしても、変更が必要なのは主に以下の二箇所だけとなる。まず、新しい支払い方法に対応する具象製品クラス(ApplePayment)を作成し、Paymentインターフェースを実装する。次に、PaymentFactoryのbuildPaymentメソッドに、新しい支払い方法を生成するための条件(case APPLE: return new ApplePayment();)を追加する。クライアント側のコードは、PaymentFactoryを使う限り、一切変更する必要がない。これは、新しい機能の追加が既存のコードに与える影響を最小限に抑え、システムの安定性を保つ上で非常に重要だ。
さらに、この考え方を別の現実世界の例に適用することもできる。エクアドルのマナビ地方にある「ピカンテリア」(レストラン)のソフトウェアを想像してみよう。このレストランでは、「セビチェ」という料理を提供するが、セビチェには魚、エビ、ミックスなど、いくつかの種類がある。これらはすべて「セビチェ」という共通の概念を持つが、それぞれ異なる材料や調理方法を必要とする。Factory Methodを適用すると、Cevicheというインターフェースを定義し、FishCeviche、ShrimpCeviche、MixedCevicheといった具象クラスがそれを実装する。そして、ManabitaRestaurantFactoryのようなファクトリークラスが、注文されたセビチェの種類に応じて適切なセビチェオブジェクトを生成し、提供するようになる。この場合も、レストランの注文システムは、具体的なセビチェの種類を気にすることなく、ファクトリーにセビチェの生成を依頼するだけでよいのだ。
Factory Methodは、このようにオブジェクト生成の責任を集中させ、プログラムの各部品が具体的なクラスに直接依存するのを防ぐことで、システム全体の柔軟性、拡張性、そして保守性を大きく向上させる強力なデザインパターンだ。システムエンジニアにとって、このようなパターンを理解し活用することは、高品質で持続可能なソフトウェアを開発するために不可欠なスキルとなる。