オブジェクト指向プログラミングにおいて、ファクトリメソッドパターンは、オブジェクトの正確なクラスを指定することなくオブジェクトを作成するという問題を解決するためにファクトリメソッドを使用するデザインパターンです。コンストラクタを呼び出す代わりに、ファクトリメソッドを呼び出してオブジェクトを作成します。ファクトリメソッドは、インターフェースで指定してサブクラスで実装することも、基底クラスで実装してサブクラスでオプションでオーバーライドすることもできます。これは、 『デザインパターン』という書籍で説明されている23の古典的なデザインパターンの1つであり、生成パターンとして分類されます。[ 1 ]
ファクトリーメソッド設計パターンは、次のような問題を解決します。
これにより、オブジェクトの作成方法を変更できるサブクラスを作成できます(たとえば、インスタンス化するクラスを再定義するなど)。
『デザインパターン:再利用可能なオブジェクト指向ソフトウェアの要素』によると、「オブジェクトを作成するためのインターフェースを定義しますが、どのクラスをインスタンス化するかはサブクラスに決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに委譲できます。」[ 2 ]
オブジェクトの作成には、構成オブジェクト内に含めるには不適切な複雑なプロセスが必要となる場合が多い。オブジェクトの作成によってコードが大幅に重複したり、構成オブジェクトからアクセスできない情報が必要になったり、十分な抽象化レベルが得られなかったり、あるいは構成オブジェクトの関心事に含まれなかったりする可能性がある。ファクトリーメソッド設計パターンは、オブジェクトを作成するための別のメソッドを定義することでこれらの問題を解決し、サブクラスはこのメソッドをオーバーライドして作成される派生型の製品を指定することができる。
ファクトリーメソッドパターンは継承に依存しており、オブジェクトの作成は、オブジェクトを作成するファクトリーメソッドを実装するサブクラスに委譲されます。[ 3 ]このパターンはインターフェース の実装にも依存できます。

上記のUMLクラス図では、オブジェクトCreatorを必要とするクラスは、そのクラスを直接Productインスタンス化しません。代わりに、別のオブジェクトを参照して製品オブジェクトを作成します。これにより、インスタンス化される具体的なクラスから独立します。のサブクラスは、インスタンス化するクラスを再定義できます。この例では、サブクラスはクラスをインスタンス化することで抽象クラスを実装します。Product1CreatorfactoryMethod()CreatorCreatorCreator1factoryMethod()Product1
迷路ゲームには2つのモードがあり、1つは隣接する部屋とのみ繋がっている通常の部屋を使用するモード、もう1つはプレイヤーがランダムに移動できる魔法の部屋を使用するモードです。

RoomMagicRoomは最終製品(または)の基底クラスですOrdinaryRoom。MazeGameは、そのような基底製品を生成する抽象ファクトリメソッドを宣言します。MagicRoomおよび は、OrdinaryRoom最終製品を実装する基底製品のサブクラスです。MagicMazeGameおよび は、最終製品を生成するファクトリメソッドを実装するOrdinaryMazeGameのサブクラスです。 ファクトリメソッドは、呼び出し元( )を具象クラスの実装から分離します。 これにより、演算子が冗長になり、オープン/クローズドの原則に従うことが可能になり、変更が発生した場合でも最終製品の柔軟性が向上します。MazeGameMazeGamenew
このC++23の実装は、デザインパターンの本にあるC++98以前の実装に基づいています。[ 5 ]
import std ;std :: unique_ptrを使用します。// ファクトリ メソッドが作成するオブジェクトのインターフェースを定義します。class Product { public : enum class Id : char { MINE , YOURS , };virtual void print () = 0 ; virtual ~ Product () = default ; };// Product インターフェースを実装します。class ConcreteProductMine : public Product { public : void print () { std :: println ( "this={} print MINE" , this ); } };// Product インターフェースを実装します。class ConcreteProductYours : public Product { public : void print () { std :: println ( "this={} print YOURS" , this ); } };// Product 型のオブジェクトを返すファクトリ メソッドを宣言します。class Creator { public : virtual unique_ptr < Product > create ( Product :: Id id ) { switch ( id ) { case Product :: Id :: MINE : return std :: make_unique < ConcreteProductMine > (); case Product :: Id :: YOURS : return std :: make_unique < ConcreteProductYours > (); // 残りの製品についても同様に繰り返します} std :: unreachable (); }virtual ~ Creator () = default ; };int main ( int argc , char * argv []) { unique_ptr < Creator > creator = std :: make_unique < Creator > (); unique_ptr < Product > product = creator -> create ( Product :: Id :: MINE ); product -> print ();product = creator -> create ( Product :: Id :: YOURS ); product -> print (); }プログラムの出力は次のようになります。
this = 0x6e5e90 print MINE this = 0x6e62c0 print YOURS// 実際のオブジェクトの空の語彙public interface IPerson { string GetName (); }public class Villager : IPerson { public string GetName () { return "村人" ; } }public class CityPerson : IPerson { public string GetName () { return "City Person" ; } }public enum PersonType { Rural , Urban }/// <summary> /// ファクトリの実装 - オブジェクトを作成するために使用されます。/// </summary> public class PersonFactory { public IPerson GetPerson ( PersonType type ) { switch ( type ) { case PersonType . Rural : return new Villager (); case PersonType . Urban : return new CityPerson (); default : throw new NotSupportedException (); } } }上記のコードは、というインターフェースと、およびIPersonという2つの実装の作成を示しています。オブジェクトに渡された型に基づいて、元の具体的なオブジェクトがインターフェースとして返されます。VillagerCityPersonPersonFactoryIPerson
ファクトリメソッドは、PersonFactoryクラスへの追加機能にすぎません。インターフェースを介してクラスのオブジェクトを作成するだけでなく、サブクラスがどのクラスをインスタンス化するかを決定できるようにします。
public interface IProduct { string GetName (); bool SetPrice ( double price ); }public class Phone : IProduct { private double _price ;public string GetName () { return "Apple TouchPad" ; }public bool SetPrice ( double price ) { _price = price ; return true ; } }// ファクトリーとほぼ同じですが、作成されたメソッドで何かを行うための追加の公開機能があります。public abstract class ProductAbstractFactory { protected abstract IProduct MakeProduct ();public IProduct GetObject () // ファクトリメソッドの実装。{ return this.MakeProduct () ; } }public class PhoneConcreteFactory : ProductAbstractFactory { protected override IProduct MakeProduct () { IProduct product = new Phone (); // オブジェクトを受け取った後に何らかの処理を行うproduct . SetPrice ( 20.30 ); return product ; } }この例では、MakeProductは で使用されますconcreteFactory。そのため、MakeProduct()から を取得するために が呼び出される可能性がありますIProduct。具体的なファクトリ メソッドでオブジェクトが取得された後、カスタム ロジックが実行される場合があります。GetObjectはファクトリ インターフェースで抽象化されます。
このJavaの例は、 『デザインパターン』という書籍に掲載されている例と似ています。
![]()
これMazeGameは、オブジェクトRoomを作成する責任をRoomサブクラスに委譲し、サブクラスが具体的なクラスを作成します。通常のゲームモードでは、このテンプレートメソッドを使用できます。
import java.util.ArrayList ; import java.util.List ;abstract class Room { abstract void connect ( Room room ); }class MagicRoom extends Room { public void connect ( Room room ) {} }class OrdinaryRoom extends Room { public void connect ( Room room ) {} }abstract class MazeGame { private final List < Room > rooms = new ArrayList <> ();public MazeGame ( ) { Room room1 = makeRoom ( ); Room room2 = makeRoom () ; room1.connect ( room2 ) ; rooms.add ( room1 ) ; rooms.add ( room2 ) ; }abstract protected Room makeRoom (); }コンストラクタは、共通のロジックを追加するテンプレートメソッドMazeGameです。これは、サブクラスで他の部屋を使用できるように、部屋の作成をカプセル化するファクトリメソッドを参照します。魔法の部屋がある別のゲームモードを実装するには、このメソッドをオーバーライドできます。makeRoom()makeRoom
class MagicMazeGame extends MazeGame { @Override protected MagicRoom makeRoom () { return new MagicRoom (); } }class OrdinaryMazeGame extends MazeGame { @Override protected OrdinaryRoom makeRoom () { return new OrdinaryRoom (); } }MazeGame ordinaryGame = new OrdinaryMazeGame (); MazeGame magicGame = new MagicMazeGame ();このPHPの例では、サブクラス化ではなくインターフェースの実装を示しています(ただし、サブクラス化でも同じことが実現できます)。ファクトリメソッドは、publicクライアントコードから直接定義して呼び出すこともできます(前のJavaの例とは対照的です)。
/* 工場および車両インターフェース */interface CarFactory { public function makeCar () : Car ; }interface Car { public function getType () : string ; }/* 工場と車の具体的な実装 */class SedanFactory implements CarFactory { public function makeCar () : Car { return new Sedan (); } }class Sedan implements Car { public function getType () : string { return 'Sedan' ; } }/* クライアント */$factory = new SedanFactory (); $car = $factory- > makeCar (); print $car- > getType ();このPythonの例では、前のJavaの例と同じ方法を採用しています。
from abc import ABC , abstractmethodclass MazeGame ( ABC ): def __init__ ( self ) -> None : self . rooms = [] self . _prepare_rooms ()def _prepare_rooms ( self ) -> None : room1 = self . make_room () room2 = self . make_room ()room1.connect ( room2 ) self.rooms.append ( room1 ) self.rooms.append ( room2 )def play ( self ) -> None : print ( f " { self.rooms [ 0 ] }を使用してプレイしています" )@abstractmethod def make_room ( self ): raise NotImplementedError ( "これを実装する必要があります!" )class MagicMazeGame ( MazeGame ): def make_room ( self ) -> "MagicRoom" : return MagicRoom ()class OrdinaryMazeGame ( MazeGame ): def make_room ( self ) -> "OrdinaryRoom" : return OrdinaryRoom ()class Room ( ABC ): def __init__ ( self ) -> None : self . connected_rooms = []def connect ( self , room : " Room " ) - > None : self.connected_rooms.append ( room )class MagicRoom ( Room ): def __str__ ( self ) -> str : return "Magic room"class OrdinaryRoom ( Room ): def __str__ ( self ) -> str : return "Ordinary room"ordinaryGame = OrdinaryMazeGame ( ) ordinaryGame.play ( )magicGame = MagicMazeGame ( ) magicGame.play ( )