はじめに
ソフトウェア設計におけるオブジェクトの生成の責任をサブクラスに委譲するFactory Methodパターンについて解説します。オブジェクトを直接生成するのではなく、特定のメソッドを通してオブジェクトを生成する手法を取り上げます。
Factory Methodパターンとは
Factory Methodパターンは、具体的なクラスを指定せずにインスタンスを生成するためのインターフェースを提供します。具体的なインスタンスの生成は、サブクラスの責任となります。
パターンの構造
Factory Methodパターンには以下の主要な構成要素があります:
- Creator: インスタンスの生成のためのメソッドのインターフェースを持ちます。
- ConcreteCreator: 実際のオブジェクトの生成を行うFactory Methodの実装を持ちます。
- Product: 生成されるオブジェクトのインターフェースを定義します。
- ConcreteProduct:
Product
インターフェースの実際の実装を持ちます。
パターンの適用
Factory Methodは以下のような状況で適用されます:
- システムが、生成されるオブジェクトの具体的なクラスを予め知らない場合。
- システムが、サブクラスがどのクラスをインスタンス化するかを決定させるように設計されている場合。
パターンの利点と欠点
利点
- 柔軟性: オブジェクトの生成のためのコードを中心化し、変更や拡張を容易にします。
- 疎結合: システムの各部分を疎結合に保ちます。これにより、オブジェクトの生成の方法やタイプが変わってもシステム全体に影響を及ぼしにくくなります。
欠点
- サブクラス化が必要: 新しいオブジェクトタイプを追加するためには新しいサブクラスを作成する必要があります。
実際のコード
Java:
// Product
interface Product {
void displayProduct();
}
class ConcreteProductA implements Product {
public void displayProduct() {
System.out.println("This is Product A");
}
}
class ConcreteProductB implements Product {
public void displayProduct() {
System.out.println("This is Product B");
}
}
// Creator
abstract class Creator {
public abstract Product factoryMethod();
}
class ConcreteCreatorA extends Creator {
public Product factoryMethod() {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
public Product factoryMethod() {
return new ConcreteProductB();
}
}
public class FactoryMethodDemo {
public static void main(String[] args) {
Creator creatorA = new ConcreteCreatorA();
Product productA = creatorA.factoryMethod();
productA.displayProduct();
Creator creatorB = new ConcreteCreatorB();
Product productB = creatorB.factoryMethod();
productB.displayProduct();
}
}
Kotlin:
// Product
interface Product {
fun displayProduct()
}
class ConcreteProductA : Product {
override fun displayProduct() {
println("This is Product A")
}
}
class ConcreteProductB : Product {
override fun displayProduct() {
println("This is Product B")
}
}
// Creator
abstract class Creator {
abstract fun factoryMethod(): Product
}
class ConcreteCreatorA : Creator() {
override fun factoryMethod(): Product {
return ConcreteProductA()
}
}
class ConcreteCreatorB : Creator() {
override fun factoryMethod(): Product {
return ConcreteProductB()
}
}
fun main() {
val creatorA = ConcreteCreatorA()
val productA = creatorA.factoryMethod()
productA.displayProduct()
val creatorB = ConcreteCreatorB()
val productB = creatorB.factoryMethod()
productB.displayProduct()
}
Factory Methodパターンは、オブジェクトの生成をサブクラスに委譲することで、システムの柔軟性と疎結合性を高めるための一般的な手法を提供します。
実際の利用シナリオ
Factory Methodパターンは、多くのソフトウェアライブラリやフレームワークで見られます。例えば、グラフィカルユーザーインターフェースのライブラリでは、異なるOSやデバイスに合わせて異なるボタンやウィンドウを生成するために、このパターンを使用しています。
また、データベース接続の管理や、クラウドリソースの生成など、具体的な実装を隠蔽しながら柔軟にオブジェクトを生成したい場合にもよく利用されます。
Factory MethodとAbstract Factoryの違い
Factory MethodとAbstract Factoryはよく混同されることがあります。簡単に違いを説明すると、Factory Methodは一つのメソッドがオブジェクトを生成することに焦点を当てているのに対し、Abstract Factoryは関連するオブジェクトのグループを生成するための一連のメソッドを提供します。
具体的には、Factory MethodはCreator
が一つのProduct
を生成することに特化しています。一方、Abstract Factoryでは複数のProduct
を生成するための複数の方法が定義されています。
まとめ
Factory Methodパターンは、オブジェクトの生成をサブクラスに委譲することで、システムの柔軟性と疎結合性を高める設計パターンです。具体的なクラスを直接インスタンス化するのではなく、Factory Methodを通じてオブジェクトを生成することで、システム全体の依存性を低減し、保守性や拡張性を向上させることができます。
このパターンを理解し適切に使用することで、ソフトウェアの品質を向上させることができるでしょう。