Das Builder-Pattern
Erstellen Sie Objekte Schritt für Schritt.
Das Builder-Pattern ist eine kostenlose Learn Rust Coding-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Learn Rust Coding-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Learn Rust Coding-Kurs umfasst insgesamt 4 Lektionen.
Warum ein Builder?
Rust kennt keine benannten oder optionalen Funktionsargumente. Wenn eine Struktur viele Felder besitzt, insbesondere optionale, wird ein Konstruktor mit acht Positionsparametern unübersichtlich und fehleranfällig.
Das Builder-Muster löst dieses Problem. Sie konfigurieren ein Objekt Schritt für Schritt mit benannten Methoden und rufen anschließend build() auf, um den Wert zu erzeugen. Der Code liest sich wie ein flüssiger Satz.
Die Zielstruktur
Beginnen Sie mit dem Typ, den Sie tatsächlich erzeugen möchten. Hier enthält eine Serverkonfiguration einen erforderlichen Host sowie mehrere optionale Einstellungen.
Beachten Sie, dass die Felder privat sind. Dadurch wird die Erstellung über den Builder statt über Struktur-Literale gefördert.
pub struct ServerConfig {
host: String,
port: u16,
max_connections: usize,
use_tls: bool,
}Ein separater Builder-Typ
Der klassische Ansatz verwendet eine zweite Struktur, den Builder. Er bildet das Zielobjekt nach, speichert aber den aktuellen Bearbeitungsstand. Optionale Felder werden häufig zu Option<T>, damit zwischen „nicht gesetzt“ und „explizit gesetzt“ unterschieden werden kann.
pub struct ServerConfigBuilder {
host: String,
port: Option<u16>,
max_connections: Option<usize>,
use_tls: bool,
}Den Builder starten
Geben Sie dem Builder einen Konstruktor, der nur die erforderlichen Felder entgegennimmt. Alle optionalen Felder beginnen mit None oder einem Standardwert.
Eine verbreitete Konvention ist eine Methode builder() am Zieltyp, die den Builder zurückgibt.
impl ServerConfig {
pub fn builder(host: impl Into<String>) -> ServerConfigBuilder {
ServerConfigBuilder {
host: host.into(),
port: None,
max_connections: None,
use_tls: false,
}
}
}Setter-Methoden übernehmen self per Wert
Jeder Setter übernimmt self, verändert ein Feld und gibt self zurück. Durch die Rückgabe des besessenen Werts können Sie Aufrufe flüssig verketten.
Diese auf Besitz basierende Verkettung entspricht dem idiomatischen Rust-Stil und vermeidet Schwierigkeiten mit Lebensdauern.
impl ServerConfigBuilder {
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn use_tls(mut self, yes: bool) -> Self {
self.use_tls = yes;
self
}
}Standardwerte in build() anwenden
Das abschließende build() wandelt den Builder in den tatsächlichen Typ um. Hier füllen Sie für alles, was noch None ist, mithilfe von unwrap_or Standardwerte ein.
impl ServerConfigBuilder {
pub fn build(self) -> ServerConfig {
ServerConfig {
host: self.host,
port: self.port.unwrap_or(8080),
max_connections: self.max_connections.unwrap_or(128),
use_tls: self.use_tls,
}
}
}Flüssige Erstellung
Nun liest sich die Erstellung von oben nach unten. Erforderliche Daten werden an builder() übergeben; jede optionale Anpassung erfolgt durch einen eindeutig benannten Aufruf.
Felder, die Sie überspringen, erhalten automatisch ihre Standardwerte.
fn main() {
let cfg = ServerConfig::builder("localhost")
.port(9000)
.use_tls(true)
.build();
println!("{}:{} tls={}", cfg.host, cfg.port, cfg.use_tls);
}Ein vollständiges ausführbares Beispiel
Hier ist das gesamte Muster in einem ausführbaren Programm zusammengefasst. Es zeigt, dass übersprungene Felder innerhalb von build() auf Standardwerte zurückfallen.
struct Config { name: String, retries: u32 }
struct Builder { name: String, retries: Option<u32> }
impl Config {
fn builder(name: &str) -> Builder {
Builder { name: name.to_string(), retries: None }
}
}
impl Builder {
fn retries(mut self, n: u32) -> Self { self.retries = Some(n); self }
fn build(self) -> Config {
Config { name: self.name, retries: self.retries.unwrap_or(3) }
}
}
fn main() {
let c = Config::builder("job").build();
println!("{} retries={}", c.name, c.retries);
}Fehlerbehaftetes build mit Result
Manchmal kann eine Konfiguration ungültig sein, zum Beispiel bei einem Port mit dem Wert null. Lassen Sie build() ein Result zurückgeben, damit Validierungsfehler als behandelbare Fehler statt als Paniken sichtbar werden.
impl ServerConfigBuilder {
pub fn try_build(self) -> Result<ServerConfig, String> {
let port = self.port.unwrap_or(8080);
if port == 0 {
return Err("port must be non-zero".into());
}
Ok(ServerConfig { host: self.host, port,
max_connections: self.max_connections.unwrap_or(128),
use_tls: self.use_tls })
}
}Das Crate derive_builder
Builder von Hand zu schreiben ist wiederholungsreich. Das Crate derive_builder erzeugt den gesamten Builder aus einer Annotation.
Sie versehen die Felder mit Standardwerten und erhalten kostenlos einen generierten FooBuilder mit Settern und einem fehlerbehafteten build().
use derive_builder::Builder;
#[derive(Builder)]
struct Channel {
#[builder(default = "8080")]
port: u16,
name: String,
}Builder mit Besitz vs. mit veränderlicher Referenz
Es gibt zwei Stile. Der Besitz-Stil übernimmt self und lässt sich natürlich verketten. Der Stil mit &mut self gibt &mut Self zurück und ermöglicht es, die Erstellung über mehrere Anweisungen zu verteilen, ohne die Variable neu binden zu müssen.
Der Besitz-Stil ist bei einer einmaligen Erstellung üblicher; der veränderliche Stil eignet sich für bedingte Konfiguration in Schleifen.
impl ServerConfigBuilder {
pub fn port_ref(&mut self, port: u16) -> &mut Self {
self.port = Some(port);
self
}
}Kurztest
Testen Sie Ihr Verständnis des Builder-Stils mit besessenem self.
Zusammenfassung
Das Builder-Muster umgeht Rusts fehlende optionalen Argumente. Ein Builder-Typ speichert den aktuellen Bearbeitungsstand, Setter übernehmen und geben self zur Verkettung zurück, und build() wendet Standardwerte an, um den endgültigen Wert zu erzeugen.
Verwenden Sie in build() ein Result für die Validierung und greifen Sie auf derive_builder zurück, um den wiederholten Code zu vermeiden.
Häufig gestellte Fragen
Ist die Lektion „Das Builder-Pattern“ kostenlos?
Ja — der vollständige Text von „Das Builder-Pattern“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Learn Rust Coding-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Learn Rust Coding-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Das Builder-Pattern“?
Erstellen Sie Objekte Schritt für Schritt. Du übst Learn Rust Coding mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Learn Rust Coding zu starten?
Keine Vorkenntnisse erforderlich. Learn Rust Coding auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.
Wie lange dauert die Lektion „Das Builder-Pattern“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Learn Rust Coding-Lektion Code schreiben und ausführen?
Ja. Jede Learn Rust Coding-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Das Builder-Pattern
- Das Newtype-Pattern
- Builder mit Type-State
- Deref und ergonomische Wrapper