Cheatsheet: Factory em Zig

Factory em Zig

O padrão Factory encapsula a lógica de criação de objetos, permitindo que o código cliente crie instâncias sem conhecer os detalhes de implementação. Em Zig, esse padrão é elegantemente implementado usando comptime, tagged unions e funções de inicialização.

Quando Usar

  • Criação de objetos depende de configuração ou parâmetros de runtime
  • Diferentes implementações de uma mesma interface
  • Encapsular lógica complexa de inicialização
  • Criar objetos para diferentes plataformas ou backends

Factory Function Simples

const std = @import("std");

const Transporte = union(enum) {
    carro: Carro,
    bicicleta: Bicicleta,
    onibus: Onibus,

    const Carro = struct { velocidade_max: u32 = 120, assentos: u8 = 5 };
    const Bicicleta = struct { velocidade_max: u32 = 30, assentos: u8 = 1 };
    const Onibus = struct { velocidade_max: u32 = 80, assentos: u8 = 40 };

    pub fn criar(tipo: []const u8) !Transporte {
        if (std.mem.eql(u8, tipo, "carro")) return .{ .carro = .{} };
        if (std.mem.eql(u8, tipo, "bicicleta")) return .{ .bicicleta = .{} };
        if (std.mem.eql(u8, tipo, "onibus")) return .{ .onibus = .{} };
        return error.TipoDesconhecido;
    }

    pub fn velocidadeMax(self: Transporte) u32 {
        return switch (self) {
            .carro => |c| c.velocidade_max,
            .bicicleta => |b| b.velocidade_max,
            .onibus => |o| o.velocidade_max,
        };
    }

    pub fn assentos(self: Transporte) u8 {
        return switch (self) {
            .carro => |c| c.assentos,
            .bicicleta => |b| b.assentos,
            .onibus => |o| o.assentos,
        };
    }
};

pub fn main() !void {
    const t = try Transporte.criar("carro");
    std.debug.print("Velocidade máx: {d} km/h\n", .{t.velocidadeMax()});
    std.debug.print("Assentos: {d}\n", .{t.assentos()});
}

Factory Genérica com comptime

const std = @import("std");

fn Serializador(comptime formato: []const u8) type {
    if (std.mem.eql(u8, formato, "json")) {
        return struct {
            pub fn serializar(dados: anytype, writer: anytype) !void {
                try std.json.stringify(dados, .{}, writer);
            }
        };
    } else if (std.mem.eql(u8, formato, "csv")) {
        return struct {
            pub fn serializar(dados: anytype, writer: anytype) !void {
                const fields = std.meta.fields(@TypeOf(dados));
                inline for (fields, 0..) |campo, i| {
                    if (i > 0) try writer.writeAll(",");
                    try writer.print("{any}", .{@field(dados, campo.name)});
                }
                try writer.writeAll("\n");
            }
        };
    } else {
        @compileError("Formato não suportado: " ++ formato);
    }
}

// Uso — tipo resolvido em comptime
const JsonSerializer = Serializador("json");
const CsvSerializer = Serializador("csv");

Factory com Allocator

const std = @import("std");

const Conexao = struct {
    host: []const u8,
    porta: u16,
    allocator: std.mem.Allocator,

    pub fn criar(allocator: std.mem.Allocator, config: Config) !*Conexao {
        const conn = try allocator.create(Conexao);
        conn.* = .{
            .host = try allocator.dupe(u8, config.host),
            .porta = config.porta,
            .allocator = allocator,
        };
        return conn;
    }

    pub fn destruir(self: *Conexao) void {
        self.allocator.free(self.host);
        self.allocator.destroy(self);
    }
};

const Config = struct {
    host: []const u8 = "localhost",
    porta: u16 = 5432,
    tipo: []const u8 = "postgres",
};

fn criarConexao(allocator: std.mem.Allocator, config: Config) !*Conexao {
    // Factory pode escolher implementação baseada no config
    return Conexao.criar(allocator, config);
}

Quando Evitar

  • Objetos simples que não precisam de lógica de criação complexa
  • Quando a construção direta com .{ ... } é clara o suficiente
  • Abstrações desnecessárias que adicionam complexidade sem benefício

Veja Também

  • Builder — Construção passo a passo de objetos complexos
  • Singleton — Garantir instância única
  • Comptime — Factory usando metaprogramação
  • Structs — Inicialização de structs em Zig
  • Enums e Unions — Tagged unions para polimorfismo

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.