Menu
Coddy logo textTech

ファクトリパターン

CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 55/61。

Factory パターンは、オブジェクトの作成を単一の関数に集約します。プログラム全体にmallocと初期化コードを分散させる代わりに、何を作成するかを決定し、すぐに使えるオブジェクトを返す1つの関数を呼び出します。

このパターンは、ポリモーフィズムと組み合わせると特に強力です。factoryは共通のbaseポインターを通じて異なる具体型を返すことができ、呼び出し元から生成の詳細を隠します。呼び出し元は単に「図形」を要求するだけで、factoryが円、長方形、または別の何かを構築するかを決定します。

典型的なファクトリー実装は次のとおりです:

typedef enum {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE
} ShapeType;

Shape* create_shape(ShapeType type) {
    switch (type) {
        case SHAPE_CIRCLE:
            return (Shape*)create_circle(5.0);
        case SHAPE_RECTANGLE:
            return (Shape*)create_rectangle(4.0, 3.0);
        default:
            return NULL;
    }
}

ファクトリは識別子(通常はenum)を受け取り、switch文を使用してどのconstructorを呼び出すかを決定します。実際に作成された型にかかわらず、Shape*を返します。呼び出し側はCircleRectangleについて知る必要がありません。単に基底型を使って動作します。

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // ポリモーフィックな呼び出し
free_shape(s);

このパターンを使うと新しい型を簡単に追加できます。新しい enum 値と factory の新しい case を追加するだけです。コードの残りの部分は変更されません。

challenge icon

チャレンジ

簡単

Pet Factoryを構築しましょう。これは、単一のfactory functionを通じてさまざまな種類のペットを作成するシステムです。コード全体に作成ロジックを分散させる代わりに、入力identifierに基づいてどの種類のペットを作成するかを決定する1か所に集約します。

コードを3つのファイルに整理します。

  • pet.h: PET_DOGPET_CATPET_BIRDの値を持つPetType enumをDefineします。speakconst Pet*を受け取り、何も返さない)へのfunction pointerを含むbase Pet structをcreateします。PetTypeを受け取りPet*を返すfactory function create_petと、cleanup用のfree_pet functionをDeclareします。
  • pet.c: 3つの具体的なpet struct、DogCatBirdをDefineします。それぞれの最初のmemberとしてPetを埋め込みます。各型のspeak functionをImplementします。
    • DogsはWoof!をprintします。
    • CatsはMeow!をprintします。
    • BirdsはTweet!をprintします。
    各pet型のconstructor functionをcreateし、memoryをAllocateしてappropriateなspeak functionを接続します。次にcreate_pet factoryをImplementします。PetTypeに対するswitch statementを使用してcorrectなconstructorをcallし、その結果をPet*として返します。invalidな型の場合はNULLを返します。Allocateされたmemoryをreleaseするためにfree_petをImplementします。
  • main.c: pet型を表すinteger(dogは0、catは1、birdは2)をReadします。factoryを使用してappropriateなpetをcreateし、base Pet* pointerを通じてpolymorphicallyそのspeak functionをcallし、その後petをFreeします。

プログラムは、createするpetを示すintegerを1つ入力として受け取ります。

入力が0の場合の出力例:

Woof!

入力が1の場合の出力例:

Meow!

入力が2の場合の出力例:

Tweet!

Factoryパターンの優れた点は、main.cDogCatBird structについて知る必要がないことです。base Pet型だけを扱います。後から新しいpet型を追加する場合も、新しいenum値とfactory内の新しいcaseを追加するだけで済み、petを使用するコードを変更する必要はありません。

自分で試してみよう

#include <stdio.h>
#include "pet.h"

int main(void) {
    int type;
    scanf("%d", &type);
    
    // TODO: ファクトリーを使って適切なペットを作成する
    // ヒント: int を PetType にキャストする
    
    // TODO: Pet* ポインタ経由でポリモーフィックに speak 関数を呼び出す
    
    // TODO: ペットを解放する
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Cオンラインコンパイラ