Padrões de Projeto em Rust: exemplos e implementação

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 com Exemplos



Padrões de projeto são soluções comprovadas para problemas típicos no desenvolvimento de software. Em Rust, devido ao seu sistema único de ownership, borrowing e lifetimes, a implementação dos padrões clássicos do GoF frequentemente requer uma abordagem especial. Neste artigo, vamos analisar vários padrões populares com exemplos de código real em Rust.



Por que o Rust muda a abordagem dos padrões?

Diferente de linguagens com garbage collection (Java, C#), o Rust impõe regras rigorosas sobre ownership de memória. Isso torna algumas implementações clássicas (como Singleton através de estado mutável global) inseguras ou ineficientes. No entanto, o Rust oferece suas próprias alternativas elegantes, baseadas em tipos e traits.



1. Builder — criação passo a passo de objetos

Builder é um dos padrões mais usados em Rust. Ele é ideal para configurar estruturas complexas, especialmente quando há muitos campos opcionais.



Exemplo: criando uma requisição HTTP

struct Request {    method: String,    url: String,    headers: Vec<(String, String)>,    body: Option<String>,}

struct RequestBuilder { method: String, url: String, headers: Vec<(String, String)>, body: Option<String>,}

impl RequestBuilder { fn new(method: &str, url: &str) -> Self { Self { method: method.to_string(), url: url.to_string(), headers: Vec::new(), body: None, } }

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

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

fn build(self) -> Request { Request { method: self.method, url: self.url, headers: self.headers, body: self.body, } }}

fn main() { let req = RequestBuilder::new("POST", "https://api.example.com/data") .header("Content-Type", "application/json") .header("Authorization", "Bearer token123") .body(r#"{"key": "value"}"#) .build();

println!("URL: {}", req.url); println!("Headers count: {}", req.headers.len());}


Vantagens da abordagem em Rust

  • Segurança: o objeto só é criado após chamar build() — configuração incompleta é impossível.
  • Legibilidade: a cadeia de métodos é intuitiva.
  • Type safety: o compilador verifica os tipos em cada etapa.


2. Strategy — seleção de algoritmo em tempo real

Strategy permite alterar o comportamento de um objeto durante a execução. Em Rust, isso é implementado através de traits e dispatch dinâmico (Box com traits) ou estático (generics).



Exemplo: ordenação de dados

trait SortStrategy {    fn sort(&self, data: &mut [i32]);}

struct BubbleSort;struct QuickSort;

impl SortStrategy for BubbleSort { fn sort(&self, data: &mut [i32]) { // Implementação simples de bubble sort for i in 0..data.len() { for j in 0..data.len() - 1 - i { if data[j] > data[j + 1] { data.swap(j, j + 1); } } } }}

impl SortStrategy for QuickSort { fn sort(&self, data: &mut [i32]) { // Quick sort (simplificado) if data.len() > 1 { let pivot = data.len() / 2; data.sort(); // Usando o sort embutido como exemplo } }}

struct Sorter { strategy: Box<dyn SortStrategy>,}

impl Sorter { fn new(strategy: Box<dyn SortStrategy>) ->

Blogs

Book Recommendations