♟️

[Rustのデザインパターン学習] Strategy [振る舞い]

2023/01/29に公開

https://rust-unofficial.github.io/patterns/patterns/behavioural/strategy.html

はじめに

  • 上記リンクで、サンプルコードは3例記載されています

    1. トレイトを使った実装
    2. クロージャを使った実装
    3. Options's map メソッドでのStrategyパターン活用例

  • Strategyパターンの学習内容

    • 1のトレイトを使ったサンプルコードを、クロージャを使った実装に変更

内容

main.rs
use std::collections::HashMap;

type RowData = HashMap<String, u32>;

struct Reporter;
impl Reporter {
    pub fn generate<F>(data: &RowData, buf:&mut String, f: F)
    where
        F: Fn(&RowData, &mut String),
    {
        f(data, buf)
    }                       
}

fn main() {    
    let data = HashMap::from([
        ("one".to_string(), 1),
        ("two".to_string(), 2),
    ]) ;
    
    text_gen(&data);   
    json_gen(&data);
}
main.rs
fn text_gen(data:&RowData){
    let mut s = String::from("");

    // 半角スペース区切りで1行ずつ格納
    let text = |data:&RowData, buf:&mut String| {
        for (k, v) in data {
            let entry = format!("{} {}\n", k, v);
            buf.push_str(&entry);
        }
    };

    Reporter::generate(&data, &mut s, text);
    println!("{}", s);   
}

実行結果
one 1
two 2

main.rs
fn json_gen(data:&RowData){
    let mut s = String::from("");

    // ネストしないオブジェクトを1行で格納
    let json = |data:&RowData, buf:&mut String| {
        buf.push('[');
        for (k, v) in data.into_iter() {
            let entry = format!(r#"{{"{}":"{}"}}"#, k, v);
            buf.push_str(&entry);
            buf.push(',');
        }
        buf.pop(); // 最後のカンマは切り捨て
        buf.push(']');
    };

    Reporter::generate(&data, &mut s, json);
    println!("{}", s);   
}

実行結果
[{"one":"1"},{"two":"2"}]

学習結果

  • クロージャ≒ラムダ式な件

    • クロージャ、矢印がないので初見の文法かな?という印象があった
  • 2周目の学習ポイント

    • type RowDataを定義しているが、複数の入力フォーマットがあった場合にどのように対応していくか

Discussion