🏗️

[Rustのデザインパターン学習] Builder [生成]

2023/01/08に公開

https://rust-unofficial.github.io/patterns/patterns/creational/builder.html

前提

  • リンクページ最下部のSee alsoセクションで紹介されているderive_builderクレートを使用

内容

  • Builderパターンを使い、{日付、内容}項目を持つ日記オブジェクトを作成

    サンプルでは2項目に絞っていますが、Builderパターンを用いることで、
    項目が増えてもオブジェクトを扱いやすくなるのではないでしょうか

main.rs
#[macro_use]
extern crate derive_builder;
use chrono::prelude::*;

#[derive(Debug,Builder)]
pub struct Diary {
    date:NaiveDate,
    content:String,
}

fn main() {
    let today_diary = DiaryBuilder::default()
        .date(Utc::now().date_naive())
        .content("It's sunny today.".to_string())
        .build();

    println!("{:#?}",today_diary.unwrap());    
}
実行結果
Diary {
    date: 2023-01-08,
    content: "It's sunny today.",
}
Cargo.toml
Cargo.toml
[package]
name = "design_pattern"
version = "0.1.0"
edition = "2021"

[dependencies]
chrono = "0.4.23"
derive_builder = "0.12.0"

学習結果

  • struct Diary#[derive(Builder)]を設定した場合
    • struct名:Diary+Builderという命名規則でDiaryBuilderが自動実装される

    • structの要素名で関数が自動実装される

今後改善したい箇所
  • date(&mut self, value: NaiveDate)で今日の日付を設定していますが、default()で設定しておきたい
    Trait std::default::Default

  • content(&mut self, value: String)の引数を&strで渡せるよう実装

    to_string()を書かなくていいように


main.rs
use chrono::prelude::*;

#[derive(Debug)]
pub struct Diary {
    date:NaiveDate,
    content:String,
}

#[derive(Default,Debug)]
pub struct DiaryBuilder {
    date:NaiveDate,
    content:String,
}

impl DiaryBuilder {
    pub fn date(mut self, date: NaiveDate) -> DiaryBuilder {
        self.date = date;
        self
    }

    pub fn content(mut self, content: &str) -> DiaryBuilder {
        self.content = content.to_string();
        self
    }

    pub fn build(self) -> Diary {
        Diary { 
            date: self.date,
            content: self.content,
        }
    }
}

fn main() {
    let today_diary = DiaryBuilder::default()
        .date(Utc::now().date_naive())
        .content("It's sunny today.")
        .build();

    println!("{:#?}",today_diary);    
}

実行結果
Diary {
    date: 2023-01-08,
    content: "It's sunny today.",
}
Cargo.toml
Cargo.toml
[package]
name = "design_pattern"
version = "0.1.0"
edition = "2021"

[dependencies]
chrono = "0.4.23"

所感

  • ぜひderive_builderクレートを使っていきたいです。

Discussion