🧖♂️
[AIがコードを書く時代 で 改めてコード設計を学ぼうシリーズ] Factoryパターン再入門
1. Factoryパターン
Factoryパターンは、オブジェクトの生成処理を専用のクラスやメソッドに移譲するパターンです。
直接new演算子を使ってインスタンスを生成するのではなく、Factory(工場) を通じてオブジェクトを生成する。
目的
- オブジェクト生成の詳細を隠蔽する。
- クライアントコードを具体的なクラスに依存させない。
- 拡張性を高める (新しい型を追加しても既存コードを変更しない)。
2. なぜFactoryパターンが必要なのか
例えば、アプリケーションで複数の種類の「製品」クラスを扱う場合、クライアントnewを使って直接生成すると、クラス名に依存してしまいます。
この状態では、製品の種類が増えるたびにクライアントコードを修正する必要があります。
Factoryパターンを使えば、生成処理を一か所にまとめることで、クライアントコードを変更せずに新しい製品を追加できます。
3. Factoryパターンの種類
Factoryパターンは以下のバリエーションを持ちます。
- Simple Factory (単純工場)
1つのFactoryクラスが複数の製品を生成する。 - Factory Method (ファクトリーメソッド)
サブクラスに生成処理を委譲する。 - Abstract Factory (抽象工場)
関連するオブジェクト群をまとめて生成する。
4. 実装例
ポイント
- クライアントはShapeFactoryに依頼するだけで、具体的なクラスを意識しません
- 新しい図形を追加する場合、Factoryクラスに条件を追加するだけ済みます。
Simple Factory
例: 図形オブジェクト生成するFactory
// 製品インターフェース
interface Shape {
void draw();
}
// 具体的な製品クラス
class Circle implements Shape {
@Override
public void draw() {
System.out.println("円を描画します。");
}
}
class Square implements Shape {
@Override
public void draw() {
System.out.println("四角形を描画します。");
}
}
// Factoryクラス
class ShapeFactory {
public Shape createShape(String type) {
if (type.equalsIgnoreCase("circle")) {
return new Circle();
} else if (type.equalsIgnoreCase("square")) {
return new Square();
}
return null;
}
}
// クライアントコード
public class Main {
public static void main(String[] args) {
ShapeFactory factory = new ShapeFactory();
Shape shape1 = factory.createShape("circle");
shape1.draw();
Shape shape2 = factory.createShape("square");
shape2.draw();
}
}
Factory Method
例: 図形オブジェクト生成するFactory
//製品インターフェース
interface Shape {
void draw();
}
//具体的な製品クラス
class Circle implements Shape {
@Override
public void draw() {
System.out.println("円を描画します");
}
}
class Square implements Shape {
@Override
public void draw() {
System.out.println("四角形を描画します");
}
}
// 抽象ファクトリ
abstract class ShapeFactory {
public abstract Shape createShape(); // Factory Method
}
// 具体ファクトリ
class CircleFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Circle();
}
}
class SquareFactory extends ShapeFactory {
@Override
public Shape createShape() {
return new Square();
}
}
public class Main() {
public static void main(String[] args) {
ShapeFactory factory1 = new CircleFactory();
Shape circle = factory1.createShape();
circle.draw();
ShapeFactory factory2 = new SquareFactory();
Shape square = factory2.createShape();
square.draw();
}
}
Abstract Factory
関連する製品群(同じテーマ・スタイルの円と四角形など)を一貫性のある組み合せで生成します。
例として、ベクター描画とラスタ描画という「製品ファミリー」を定義し、それぞれが円・四角形のバリエーションをまとめて生成します。
例: 図形オブジェクト生成するFactory
//共通インターフェース
interface Shape {
void draw();
}
// ベクター系の具体製品
class VectorCircle implements Shape {
@Override
public void draw() {
System.out.println("ベクター円を描画します");
}
}
class VectorSquare implements Shape {
@Override
public void draw() {
System.out.println("ベクター四角形を描画します");
}
}
// ラスタ系の具体製品
class RasteCircle implements Shape {
@Override
public void draw() {
System.out.println("ラスタ円を描画します");
}
}
class RasterSquare implements Shape {
@Override
public void draw() {
System.out.pritln("ラスタ四角形を描画します");
}
}
// 抽象ファクトリ
interface ShapeFactory {
Shape createCircle();
Shape createSquare();
}
// 具体ファクトリ
class VectorShapeFactory implements ShapeFactory {
@Override
public Shape createCircle() {
return new VectorCIrcle();
}
@Override
public Shape createSquare() {
return new VectorSquare();
}
}
class RasterShapeFactory implements ShapeFactory {
@Override
public Shape createCircle() {
return new RasterCircle();
}
@Override
public Shape createSquare() {
return new RasterSquare();
}
}
public class Main {
public static void main(String[] args) {
ShapeFactory factory = new VectorShapeFactory();
Shape circle1 = factory.createCircle();
Shape square1 = factory.createSquare();
circle1.draw();
square1.draw();
factory = new RasterShapeFactory();
Shape circle2 = factory.createCircle();
Shape square2 = factory.createSquare();
circle2.draw();
square2.draw();
}
}
5. Factoryパターンのメリットデメリット
メリット
- オブジェクト生成の責務を分離できる
- クライアントコードの依存性を低減できる
- 拡張性が高い
デメリット
- Factoryクラスが肥大化しやすい
- クラス数が増える場合、管理が複雑になる
6. まとめ
Factoryパターンは、オブジェクト生成の柔軟性を高めるための基本的なデザインパターンで、生成処理を分離して実装するものです。
Discussion