Padrões de Projeto em Rust com Exemplos: de A a Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Padrões de Projeto em Rust: da Teoria à Prática



Padrões de projeto são soluções comprovadas para problemas recorrentes no desenvolvimento de software. Em Rust, graças ao seu sistema único de ownership (propriedade) e à ausência de POO clássica, muitos padrões clássicos ganham uma nova roupagem. Neste artigo, abordaremos quatro padrões-chave: Singleton, Factory, Builder e Strategy, adaptados para o Rust idiomático.



1. Singleton (Instância Única) em Rust



Rust não possui variáveis estáticas globais no sentido tradicional. No entanto, o Singleton pode ser implementado através de lazy_static ou OnceCell. Vejamos um exemplo com std::sync::OnceLock (disponível desde o Rust 1.70).



Implementação com OnceLock



use std::sync::OnceLock;

static CONFIG: OnceLock<Config> = OnceLock::new();

#[derive(Debug)]struct Config { db_url: String, port: u16,}

fn get_config() -> &'static Config { CONFIG.get_or_init(|| { Config { db_url: String::from("postgres://localhost"), port: 5432, } })}

fn main() { let cfg = get_config(); println!("{:?}", cfg);}


Ponto-chave: OnceLock garante inicialização única e segurança em threads. Esta é a forma idiomática para Rust.



2. Factory (Fábrica) através de Traits



O padrão Factory em Rust é implementado de forma excelente com traits. Não precisamos de classes abstratas — basta definir uma interface através de um trait.



Exemplo: criação de meios de transporte



trait Transport {    fn deliver(&self);}

struct Truck;impl Transport for Truck { fn deliver(&self) { println!("Entrega por caminhão em terra"); }}

struct Ship;impl Transport for Ship { fn deliver(&self) { println!("Entrega por navio no mar"); }}

struct LogisticsFactory;

impl LogisticsFactory { fn create_transport(route_type: &str) -> Box<dyn Transport> { match route_type { "land" => Box::new(Truck), "sea" => Box::new(Ship), _ => panic!("Tipo de rota desconhecido"), } }}

fn main() { let transport = LogisticsFactory::create_transport("sea"); transport.deliver();}


Vantagem: Rust não requer herança — o polimorfismo é alcançado através de traits e Box<dyn Trait>.



3. Builder (Construtor) com encadeamento tipado



O Builder em Rust é amplamente utilizado, especialmente para estruturas com muitos parâmetros opcionais. Vamos implementá-lo com um encadeamento tipado de métodos que retornam &mut Self.



Exemplo: criação de uma requisição HTTP



#[derive(Debug, Default)]struct HttpRequest {    url: String,    method: String,    headers: Vec<(String, String)>,    body: Option<String>,}

struct HttpRequestBuilder { request: HttpRequest,}

impl HttpRequestBuilder { fn new(url: &str) -> Self { HttpRequestBuilder { request: HttpRequest { url: url.to_string(), method: "GET".to_string(), ..Default::default() }, } }

fn method(&mut self, method: &str) -> &mut Self { self.request.method = method.to_string(); self }

fn header(&mut self, key: &str, value: &str) -> &mut Self { self.request.headers.push((key.to_string(), value.to_string())); self }

fn body(&mut self, body: &str) -> &mut Self { self.request.body = Some(body.to_string()); self }

fn build(&self) -> HttpRequest { // Aqui pode-se adicionar validação HttpRequest { ..self.request.clone() } }}

fn ma

Blogs

Book Recommendations