Categories
ドメイン駆動設計

ファクトリ

概要

ファクトリ(Factory)は、ソフトウェア開発においてオブジェクトの生成を抽象化するためのデザインパターンです。ファクトリは、オブジェクトの生成方法をカプセル化し、クライアントコードから具体的なオブジェクトの生成ロジックを隠蔽します。これにより、クライアントコードは生成されたオブジェクトの具体的なクラスに依存せずに、抽象的なインターフェースを通じてオブジェクトを作成できます。

ファクトリパターンにはいくつかの異なるバリエーションがありますが、代表的なものに以下の2つがあります。

  1. 単純なファクトリ(Simple Factory): クライアントコードに対して直接オブジェクトを生成するメソッドを提供する静的メソッドを持つクラスです。クライアントはファクトリクラスのメソッドを呼び出してオブジェクトを生成しますが、具体的なオブジェクトの生成ロジックはファクトリクラス内に隠蔽されます。
  2. ファクトリメソッド(Factory Method): オブジェクトの生成処理をサブクラスに委譲するための抽象メソッドを持つ抽象クラスまたはインターフェースです。具体的なオブジェクトの生成方法はサブクラスで実装されます。クライアントコードは抽象クラスまたはインターフェースを介してオブジェクトを生成しますが、具体的なオブジェクトのクラスはサブクラスによって決定されます。

ファクトリパターンは以下のような利点を持ちます:

  • クライアントコードと具体的なオブジェクトの生成ロジックを分離するため、クライアントコードは抽象的なインターフェースに対して操作を行うだけで済みます。
  • オブジェクトの生成ロジックをカプセル化するため、将来的な変更や拡張に柔軟に対応できます。具体的なオブジェクトの生成方法を変更する場合、クライアントコードに影響を与えずにファクトリの実装を変更することができます。
  • オブジェクトの生成ロジックを集中管理するため、コードの重複を避けることができます。複数のクライアントが同じオブジェクトを生成する場合、ファクトリを使用することで共通の生成ロジックを再利用できます。

具体的なファクトリの実装方法はプログラミング言語やアプリケーションの要件によって異なります。一般的には、単純なファクトリやファクトリメソッドを使用してオブジェクトを生成するためのクラスやメソッドを定義し、それらを適切なタイミングで呼び出すことでオブジェクトの生成を行います。

コード例

以下は、C++での単純なファクトリ(Simple Factory)のコード例です。例として、異なる形状(円形、四角形、三角形)のオブジェクトを生成する ShapeFactory クラスを作成します。

#include <iostream>
#include <memory>

// 抽象基底クラス
class Shape {
public:
    virtual void draw() = 0;
};

// 具体クラス: Circle
class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a circle." << std::endl;
    }
};

// 具体クラス: Rectangle
class Rectangle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a rectangle." << std::endl;
    }
};

// 具体クラス: Triangle
class Triangle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a triangle." << std::endl;
    }
};

// Shape オブジェクトを生成するファクトリクラス
class ShapeFactory {
public:
    static std::shared_ptr<Shape> createShape(const std::string& shapeType) {
        if (shapeType == "circle") {
            return std::make_shared<Circle>();
        } else if (shapeType == "rectangle") {
            return std::make_shared<Rectangle>();
        } else if (shapeType == "triangle") {
            return std::make_shared<Triangle>();
        } else {
            return nullptr;
        }
    }
};

int main() {
    // ShapeFactory を使用してオブジェクトを生成
    std::shared_ptr<Shape> shape1 = ShapeFactory::createShape("circle");
    shape1->draw();

    std::shared_ptr<Shape> shape2 = ShapeFactory::createShape("rectangle");
    shape2->draw();

    std::shared_ptr<Shape> shape3 = ShapeFactory::createShape("triangle");
    shape3->draw();

    return 0;
}

この例では、Shape クラスを抽象基底クラスとして定義し、Circle、Rectangle、Triangle クラスがそれを継承して具体的な形状を表現しています。

ShapeFactory クラスでは、静的な createShape メソッドを使用して異なる形状のオブジェクトを生成します。クライアントコードは ShapeFactory::createShape メソッドを呼び出すことでオブジェクトを生成し、生成されたオブジェクトの draw メソッドを呼び出して形状を描画します。

実行結果は以下のようになります:

Drawing a circle.
Drawing a rectangle.
Drawing a triangle.

この例では、単純なファクトリを使用してオブジェクトの生成を行っています。特定の形状に対して新たなクラスを追加する場合、ShapeFactory クラス内の createShape メソッドの条件文を拡張することで対応できます。また、クライアントコードは具体的なオブジェクトのクラスに依存せずに抽象的な Shape インターフェースを通じてオブジェクトを操作できます。