Javaにおけるファクトリーメソッドパターン:ポリモーフィックな製造で柔軟性を向上
別名
- 仮想コンストラクタ
ファクトリーメソッドデザインパターンの意図
ファクトリーメソッドパターンを使用してオブジェクトを作成するためのインターフェースを定義しますが、どのクラスをインスタンス化するかはサブクラスに決定させます。この生成デザインパターンは、クラスがインスタンス化をサブクラスに委ねることで、コードの柔軟性と保守性を向上させます。
ファクトリーメソッドパターンの詳細な説明と実世界の例
実世界の例
標準、速達、特大といったさまざまな種類の荷物を配達する必要がある物流会社を想像してみてください。会社には配達リクエストを処理する中央システムがありますが、各荷物タイプの処理方法の詳細はわかりません。これを管理するために、会社はファクトリーメソッドパターンを使用します。
この設定では、`createPackage()`メソッドを持つ中央の`DeliveryRequest`クラスがあります。このメソッドは、`StandardDelivery`、`ExpressDelivery`、`OversizedDelivery`などのサブクラスでオーバーライドされ、それぞれがそれぞれの荷物タイプの作成と管理方法を知っています。このようにして、中央システムは、各荷物タイプがどのように作成および処理されるかの詳細を知る必要なく配達リクエストを処理できるため、柔軟性と保守性が向上します。
平易な言葉で
インスタンス化ロジックを子クラスに委任する方法を提供します。
Wikipediaによると
クラスベースのプログラミングでは、ファクトリーメソッドパターンは、作成されるオブジェクトの正確なクラスを指定することなくオブジェクトを作成する問題に対処するためにファクトリーメソッドを使用する生成パターンです。これは、コンストラクタを呼び出すのではなく、インターフェースで指定され子クラスで実装されるか、または基本クラスで実装され、必要に応じて派生クラスでオーバーライドされるファクトリーメソッドを呼び出してオブジェクトを作成することによって行われます。
Javaにおけるファクトリーメソッドパターンのプログラム例
ファクトリーメソッドアプローチは、以下の例に見られるように、柔軟で保守性の高いコードを実現するために、Javaデザインパターンにおいて極めて重要です。
鍛冶屋は武器を製造します。エルフはエルフの武器を必要とし、オークはオークの武器を必要とします。目の前の顧客に応じて、適切なタイプの鍛冶屋が呼び出されます。
まず、`Blacksmith`インターフェースといくつかの実装があります。
public interface Blacksmith {
Weapon manufactureWeapon(WeaponType weaponType);
}
public class ElfBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return ELFARSENAL.get(weaponType);
}
}
public class OrcBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return ORCARSENAL.get(weaponType);
}
}
顧客が来ると、適切なタイプの鍛冶屋が呼び出され、要求された武器が製造されます。
public static void main(String[] args) {
Blacksmith blacksmith = new OrcBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
LOGGER.info(MANUFACTURED, blacksmith, weapon);
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
LOGGER.info(MANUFACTURED, blacksmith, weapon);
blacksmith = new ElfBlacksmith();
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
LOGGER.info(MANUFACTURED, blacksmith, weapon);
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
LOGGER.info(MANUFACTURED, blacksmith, weapon);
}
プログラム出力
06:40:07.269 [main] INFO com.iluwatar.factory.method.App -- The orc blacksmith manufactured an orcish spear
06:40:07.271 [main] INFO com.iluwatar.factory.method.App -- The orc blacksmith manufactured an orcish axe
06:40:07.272 [main] INFO com.iluwatar.factory.method.App -- The elf blacksmith manufactured an elven spear
06:40:07.272 [main] INFO com.iluwatar.factory.method.App -- The elf blacksmith manufactured an elven axe
Javaでファクトリーメソッドパターンを使用する場合
Javaでファクトリーメソッドパターンを使用する場合
- クラスが作成する必要があるオブジェクトのクラスを予測できない場合。
- クラスが、作成するオブジェクトをサブクラスに指定させたい場合。
- クラスが責任をいくつかのヘルパーサブクラスの1つに委任し、どのヘルパーサブクラスがデリゲートであるかの知識をローカライズしたい場合。
Javaにおけるファクトリーメソッドパターンの実世界の応用
- java.util.Calendar
- java.util.ResourceBundle
- java.text.NumberFormat
- java.nio.charset.Charset
- java.net.URLStreamHandlerFactory
- java.util.EnumSet
- javax.xml.bind.JAXBContext
- 実行時に動的に構成されるアプリケーションコンポーネントを実行するフレームワーク。
ファクトリーメソッドパターンの利点とトレードオフ
利点
- ファクトリーメソッドパターンは、サブクラスのフックを提供し、コードの柔軟性と保守性を向上させます。
- 並列クラス階層を接続します。
- アプリケーション固有のクラスをコードにバインドする必要性を排除します。コードは製品インターフェースのみを扱うため、ユーザー定義の具体的な製品クラスで動作できます。
トレードオフ
- 拡張されたファクトリーメソッドを実装するために新しいサブクラスを追加する必要があるため、コードが複雑になる可能性があります。
関連するJavaデザインパターン
- 抽象ファクトリー:ファクトリーメソッドは、多くの場合、抽象ファクトリーパターン内で呼び出されます。
- プロトタイプ:プロトタイプクラスのクローンであるクラスの新しいインスタンスを返すファクトリーメソッド。