春のセール
Composite

Composite を Rust で

Composite 構造に関するデザインパターンの一つで オブジェクトを木のような構造に構成し あたかも単一のオブジェクトであるかのように扱えるようにします

Composite は ツリー構造の構築を必要とする問題の大部分の解決策として かなりの人気を得るようになりました Composite の大きな特徴は ツリー構造全体でメソッドを再帰的に実行し 結果をまとめあげることです

Files and Folders

Let’s try to understand the Composite pattern with an example of an operating system’s file system. In the file system, there are two types of objects: files and folders. There are cases when files and folders should be treated to be the same way. This is where the Composite pattern comes in handy.

File and Directory are both of the trait Component with a single search method. For a file, it will just look into the contents of the file; for a folder, it will go through all files of that folder to find that keyword.

fs/mod.rs

mod file;
mod folder;

pub use file::File;
pub use folder::Folder;

pub trait Component {
    fn search(&self, keyword: &str);
}

fs/file.rs

use super::Component;

pub struct File {
    name: &'static str,
}

impl File {
    pub fn new(name: &'static str) -> Self {
        Self { name }
    }
}

impl Component for File {
    fn search(&self, keyword: &str) {
        println!("Searching for keyword {} in file {}", keyword, self.name);
    }
}

fs/folder.rs

use super::Component;

pub struct Folder {
    name: &'static str,
    components: Vec<Box<dyn Component>>,
}

impl Folder {
    pub fn new(name: &'static str) -> Self {
        Self {
            name,
            components: vec![],
        }
    }

    pub fn add(&mut self, component: impl Component + 'static) {
        self.components.push(Box::new(component));
    }
}

impl Component for Folder {
    fn search(&self, keyword: &str) {
        println!(
            "Searching recursively for keyword {} in folder {}",
            keyword, self.name
        );

        for component in self.components.iter() {
            component.search(keyword);
        }
    }
}

main.rs

mod fs;

use fs::{Component, File, Folder};

fn main() {
    let file1 = File::new("File 1");
    let file2 = File::new("File 2");
    let file3 = File::new("File 3");

    let mut folder1 = Folder::new("Folder 1");
    folder1.add(file1);

    let mut folder2 = Folder::new("Folder 2");
    folder2.add(file2);
    folder2.add(file3);
    folder2.add(folder1);

    folder2.search("rose");
}

Output

Searching recursively for keyword rose in folder Folder 2
Searching for keyword rose in file File 2
Searching for keyword rose in file File 3
Searching recursively for keyword rose in folder Folder 1
Searching for keyword rose in file File 1
------------------------------------

他言語での Composite

Composite を C# で Composite を C++ で Composite を Go で Composite を Java で Composite を PHP で Composite を Python で Composite を Ruby で Composite を Swift で Composite を TypeScript で