Menu
Coddy logo textTech

Padrão Factory

Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 55 de 61.

O padrão Factory centraliza a criação de objetos em uma única função. Em vez de espalhar o malloc e o código de inicialização por todo o seu programa, você chama uma função que decide o que criar e retorna um objeto pronto para uso.

Este padrão é especialmente poderoso quando combinado com polimorfismo. Uma factory pode retornar diferentes tipos concretos através de um ponteiro base comum, ocultando os detalhes de criação de quem faz a chamada. Quem faz a chamada apenas solicita "uma forma" e a factory decide se deve construir um círculo, retângulo ou outra coisa.

Aqui está uma implementação típica de 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;
    }
}

A fábrica recebe um identificador (geralmente um enum) e usa uma instrução switch para determinar qual construtor chamar. Ela retorna um Shape* independentemente do tipo real criado. O chamador não precisa saber sobre Circle ou Rectangle — ele apenas trabalha com o tipo base:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // chamada polimórfica
free_shape(s);

Este padrão torna a adição de novos tipos fácil: basta adicionar um novo valor de enum e um novo caso na factory. O restante do seu código permanece inalterado.

challenge icon

Desafio

Fácil

Vamos construir uma Pet Factory — um sistema que cria diferentes tipos de animais de estimação por meio de uma única função de fábrica. Em vez de espalhar a lógica de criação por todo o seu código, você a centralizará em um único lugar que decide que tipo de pet criar com base em um identificador de entrada.

Você organizará seu código em três arquivos:

  • pet.h: Defina um enum PetType com os valores PET_DOG, PET_CAT e PET_BIRD. Crie uma struct base Pet que contenha um ponteiro de função para speak (que recebe um const Pet* e não retorna nada). Declare a função de fábrica create_pet que recebe um PetType e retorna um Pet*, além de uma função free_pet para limpeza.
  • pet.c: Defina três structs de pets concretas — Dog, Cat e Bird — cada uma incorporando Pet como seu primeiro membro. Implemente uma função speak para cada tipo:
    • Cães imprimem: Woof!
    • Gatos imprimem: Meow!
    • Pássaros imprimem: Tweet!
    Crie funções construtoras para cada tipo de pet que alocam memória e configuram a função speak apropriada. Em seguida, implemente a fábrica create_pet — use uma instrução switch no PetType para chamar o construtor correto e retornar o resultado como um Pet*. Para tipos inválidos, retorne NULL. Implemente free_pet para liberar a memória alocada.
  • main.c: Leia um número inteiro representando o tipo de pet (0 para cão, 1 para gato, 2 para pássaro). Use sua fábrica para criar o pet apropriado, chame sua função speak polimorficamente através do ponteiro base Pet* e, em seguida, libere o pet.

Seu programa receberá uma entrada: um número inteiro indicando qual pet criar.

Exemplo de saída quando a entrada é 0:

Woof!

Exemplo de saída quando a entrada é 1:

Meow!

Exemplo de saída quando a entrada é 2:

Tweet!

A beleza do padrão Factory é que o main.c não precisa saber sobre as structs Dog, Cat ou Bird — ele trabalha apenas com o tipo base Pet. Adicionar um novo tipo de pet posteriormente significa adicionar um novo valor ao enum e um novo caso na fábrica, sem alterar nenhum código que utilize os pets.

Folha de consulta

O padrão Factory centraliza a criação de objetos em uma única função, escondendo os detalhes de criação de quem a chama.

Uma função factory recebe um identificador (geralmente um enum) e usa uma instrução switch para determinar qual construtor chamar, retornando um ponteiro de tipo base:

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;
    }
}

O chamador trabalha apenas com o tipo base, permitindo comportamento polimórfico:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // polymorphic call
free_shape(s);

Benefícios: Adicionar novos tipos requer apenas a adição de um novo valor de enum e um caso no switch, sem alterar o código existente que utiliza a factory.

Experimente você mesmo

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

int main(void) {
    int type;
    scanf("%d", &type);
    
    // TODO: Use a fábrica para criar o pet apropriado
    // Hint: Faça o cast do int para PetType
    
    // TODO: Chame a função speak polimorficamente através do ponteiro Pet*
    
    // TODO: Libere o pet
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming