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 o código de malloc e de inicialização por todo o 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 fábrica pode retornar diferentes tipos concretos por meio de um ponteiro para uma classe base comum, ocultando os detalhes da criação do chamador. O chamador simplesmente pede "uma forma", e a fábrica decide se deve criar um círculo, um retângulo ou outra coisa.
Esta é 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. O chamador não precisa saber sobre Circle ou Rectangle. Ele simplesmente trabalha com o tipo base:
Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s); // chamada polimórfica
free_shape(s);Este padrão facilita a adição de 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 Animais: 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 pelo seu código, você a centralizará em um único lugar que decide que tipo de animal criar com base em um identificador de entrada.
Você organizará seu código em três arquivos:
pet.h: Defina um enumPetTypecom os valoresPET_DOG,PET_CATePET_BIRD. Crie uma struct basePetque contenha um ponteiro de função paraspeak(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 a limpeza.pet.c: Defina três structs concretas de animais,Dog,CateBird, cada uma incorporandoPetcomo seu primeiro membro. Implemente uma função speak para cada tipo:- Cães imprimem:
Woof! - Gatos imprimem:
Meow! - Pássaros imprimem:
Tweet!
create_pet: use uma instrução switch sobre 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 inteiro que represente o tipo de animal (0 para cachorro, 1 para gato, 2 para pássaro). Use sua fábrica para criar o animal apropriado, chame sua funçãospeakpolimorficamente por meio do ponteiro basePet*e, em seguida, libere o animal.
Seu programa receberá uma entrada: um inteiro indicando qual animal 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 main.c não precisa conhecer as structs Dog, Cat ou Bird. Ele trabalha apenas com o tipo base Pet. Adicionar um novo tipo de animal posteriormente significa adicionar um novo valor ao enum e um novo case na fábrica, sem alterar nenhum código que use animais.
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
// Dica: 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;
}
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çalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do CírculoImplementação do RetânguloUso PolimórficoContainer de FormasPratique por conta própria: Compilador de C online