Padrão Factory
Parte da seção Programação Orientada a Objetos 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 código de malloc e de inicialização pelo programa, você chama uma função que decide o que criar e retorna um objeto pronto para uso.
Esse padrão é especialmente poderoso quando combinado com polimorfismo. Uma fábrica pode retornar tipos concretos diferentes por meio de um ponteiro para uma classe-base comum, ocultando os detalhes da criação de quem faz a chamada. Quem faz a chamada simplesmente pede “uma forma”, e a fábrica decide se deve criar um círculo, um retângulo ou outra coisa.
Veja uma implementação típica de fábrica:
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. Quem chama não precisa conhecer Circle nem Rectangle. Basta trabalhar com o tipo base:
Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s); // chamada polimórfica
free_shape(s);Esse padrão facilita adicionar novos tipos: basta adicionar um novo valor de enumeração e um novo caso na fábrica. O restante do seu código permanece inalterado.
Desafio
FácilVamos criar uma Fábrica de Pets: um sistema que cria diferentes tipos de pets por meio de uma única função de fábrica. Em vez de espalhar a lógica de criação pelo seu código, você vai centralizá-la em um só lugar, que decide que tipo de pet criar com base em um identificador de entrada.
Você vai organizar seu código em três arquivos:
pet.h: Defina um enumPetTypecom os valoresPET_DOG,PET_CATePET_BIRD. Crie uma estrutura basePetque contenha um ponteiro para a funçãospeak(que recebe umconst Pet*e não retorna nada). Declare a função de fábricacreate_pet, que recebe umPetTypee retorna umPet*, além de uma funçãofree_petpara liberar a memória.pet.c: Defina três estruturas concretas de pets,Dog,CateBird, cada uma incorporandoPetcomo seu primeiro membro. Implemente uma funçãospeakpara cada tipo:- Cães imprimem:
Woof! - Gatos imprimem:
Meow! - Pássaros imprimem:
Tweet!
speakapropriada. Em seguida, implemente a fábricacreate_pet: use uma instruçãoswitchsobre oPetTypepara chamar o construtor correto e retornar o resultado como umPet*. Para tipos inválidos, retorneNULL. Implementefree_petpara liberar a memória alocada.- Cães imprimem:
main.c: Leia um número inteiro que representa o tipo de pet (0 para cachorro, 1 para gato, 2 para pássaro). Use sua fábrica para criar o pet apropriado, chame sua funçãospeakpolimorficamente por meio do ponteiro basePet*e, em seguida, libere o pet.
Seu programa receberá uma entrada: um número inteiro que indica qual pet criar.
Exemplo de saída quando a entrada for 0:
Woof!Exemplo de saída quando a entrada for 1:
Meow!Exemplo de saída quando a entrada for 2:
Tweet!A vantagem do padrão Factory é que main.c não precisa conhecer as estruturas 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 use pets.
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 animal de estimação adequado
// Dica: Converta o int para PetType
// TODO: Chame a função speak de forma polimórfica por meio do ponteiro Pet*
// TODO: Libere a memória do animal de estimação
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos da Programação Modular
Arquivos de cabeçalhoProteções de inclusãoArquivos-fonteFunções estáticasRevisão: calculadora modular4Encapsulamento
Conceito de ponteiros opacosDefinindo structs opacasGetters e settersValidação em settersRevisão: caixa secreta2Objetos e métodos
Structs como objetosO ponteiro 'Self'Correção de constPonteiro vs. valorMétodos auxiliaresRevisão: Gerenciador de pontos5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de vida do objeto
Padrão de construtorPadrão de destrutorInicialização da pilhaCópia profundaRevisão: wrapper de String6Herança por composição
Incorporação de structRegra do primeiro membroAcessando membros do tipo paiUpcastingRevisão: hierarquia de formas9Projeto: Desenhador de Formas
Visão geral do projetoImplementação do círculoImplementação do retânguloUso polimórficoContêiner de formasPratique por conta própria: Compilador de C online