iT邦幫忙

2024 iThome 鐵人賽

DAY 14
1
Software Development

Rust 學得動嗎系列 第 14

[Day 14] 如何在Rust 中如何應用常見的軟體設計模式

  • 分享至 

  • xImage
  •  

今天,我們將試著在 Rust 中使用常見的軟體設計模式。設計模式是解決軟體設計中常見問題的可重用解決方案。雖然許多設計模式源自於物件導向程式設計,但我們可以看 Rust 的獨特環境 中適應和應用這些模式。

1. 單例模式(Singleton Pattern)

在 Rust 中,我們可以使用 lazy_static 宏來實現執行緒安全的單例模式。

use lazy_static::lazy_static;
use std::sync::Mutex;

lazy_static! {
    static ref INSTANCE: Mutex<SingletonStruct> = Mutex::new(SingletonStruct::new());
}

struct SingletonStruct {
    // 結構體欄位
}

impl SingletonStruct {
    fn new() -> Self {
        SingletonStruct {
            // 初始化欄位
        }
    }

    fn get_instance() -> &'static Mutex<Self> {
        &INSTANCE
    }
}

fn main() {
    let instance = SingletonStruct::get_instance();
    let mut singleton = instance.lock().unwrap();
    // 使用 singleton
}

https://ithelp.ithome.com.tw/upload/images/20240928/20140358IX0WalFJ5E.png

2. 工廠模式(Factory Pattern)

Rust 使用特徵(trait)來實現工廠模式。

trait Animal {
    fn make_sound(&self);
}

struct Dog;
struct Cat;

impl Animal for Dog {
    fn make_sound(&self) {
        println!("汪汪!");
    }
}

impl Animal for Cat {
    fn make_sound(&self) {
        println!("喵喵!");
    }
}

enum AnimalType {
    Dog,
    Cat,
}

struct AnimalFactory;

impl AnimalFactory {
    fn create_animal(animal_type: AnimalType) -> Box<dyn Animal> {
        match animal_type {
            AnimalType::Dog => Box::new(Dog),
            AnimalType::Cat => Box::new(Cat),
        }
    }
}

fn main() {
    let dog = AnimalFactory::create_animal(AnimalType::Dog);
    dog.make_sound();

    let cat = AnimalFactory::create_animal(AnimalType::Cat);
    cat.make_sound();
}

https://ithelp.ithome.com.tw/upload/images/20240928/20140358KU3jV7PkCK.png

3. 觀察者模式(Observer Pattern)

在 Rust 中,我們可以使用特徵和閉包來實現觀察者模式。

use std::cell::RefCell;

trait Observer {
    fn update(&self, message: &str);
}

struct Subject {
    observers: RefCell<Vec<Box<dyn Observer>>>,
}

impl Subject {
    fn new() -> Self {
        Subject {
            observers: RefCell::new(Vec::new()),
        }
    }

    fn attach(&self, observer: Box<dyn Observer>) {
        self.observers.borrow_mut().push(observer);
    }

    fn notify(&self, message: &str) {
        for observer in self.observers.borrow().iter() {
            observer.update(message);
        }
    }
}

struct ConcreteObserver {
    name: String,
}

impl Observer for ConcreteObserver {
    fn update(&self, message: &str) {
        println!("{} 收到訊息:{}", self.name, message);
    }
}

fn main() {
    let subject = Subject::new();

    let observer1 = Box::new(ConcreteObserver { name: "觀察者1".to_string() });
    let observer2 = Box::new(ConcreteObserver { name: "觀察者2".to_string() });

    subject.attach(observer1);
    subject.attach(observer2);

    subject.notify("重要更新!");
}

https://ithelp.ithome.com.tw/upload/images/20240928/20140358jxBVAYFOp9.png

4. 策略模式(Strategy Pattern)

Rust 的特徵非常適合實現策略模式。

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

struct BubbleSort;
struct QuickSort;

impl SortStrategy for BubbleSort {
    fn sort(&self, data: &mut [i32]) {
        // 實作氣泡排序
        println!("使用氣泡排序");
    }
}

impl SortStrategy for QuickSort {
    fn sort(&self, data: &mut [i32]) {
        // 實作快速排序
        println!("使用快速排序");
    }
}

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

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

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

fn main() {
    let mut data = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];

    let bubble_sorter = Sorter::new(Box::new(BubbleSort));
    bubble_sorter.sort(&mut data);

    let quick_sorter = Sorter::new(Box::new(QuickSort));
    quick_sorter.sort(&mut data);
}

https://ithelp.ithome.com.tw/upload/images/20240928/20140358zTPhaDJp8Q.png

5. 建造者模式(Builder Pattern)

Rust 的方法鏈接特性使得實現建造者模式變得很輕鬆。

#[derive(Default)]
struct Computer {
    cpu: String,
    ram: u32,
    storage: u32,
}

struct ComputerBuilder {
    computer: Computer,
}

impl ComputerBuilder {
    fn new() -> Self {
        ComputerBuilder {
            computer: Computer::default(),
        }
    }

    fn cpu(mut self, cpu: String) -> Self {
        self.computer.cpu = cpu;
        self
    }

    fn ram(mut self, ram: u32) -> Self {
        self.computer.ram = ram;
        self
    }

    fn storage(mut self, storage: u32) -> Self {
        self.computer.storage = storage;
        self
    }

    fn build(self) -> Computer {
        self.computer
    }
}

fn main() {
    let computer = ComputerBuilder::new()
        .cpu("Intel i7".to_string())
        .ram(16)
        .storage(512)
        .build();

    println!("CPU: {}, RAM: {}GB, Storage: {}GB", computer.cpu, computer.ram, computer.storage);
}

https://ithelp.ithome.com.tw/upload/images/20240928/20140358CT5Kvx0Trb.png

結論

這些例子示範了如何在 Rust 中應用一些常見的設計模式。Rust 的特性如特徵、閉包和強大的型別系統,在使用設計模式時,重要的是要考慮 Rust 的所有權系統和借用規則,以確保程式碼不僅符合模式的意圖,而且也是安全和高效。


上一篇
[Day 13] Rust 在系統程式設計中的應用
下一篇
[Day 15] Rust 在 Web 開發中的應用
系列文
Rust 學得動嗎30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言