Rust编程-核心篇-高级模式

阿里云教程1个月前发布
11 0 0

模式的力量

在软件开发中,模式是解决常见问题的可重用解决方案。Rust作为一门现代系统编程语言,不仅提供了强劲的类型系统和内存安全保证,还支持多种高级编程模式。掌握这些模式不仅能让我们写出更优雅的代码,还能提高代码的可维护性和可扩展性。

建造者模式

建造者模式在Rust中超级常见,特别是在配置复杂对象时:

#[derive(Debug, Clone)]
pub struct DatabaseConfig {
    pub host: String,
    pub port: u16,
    pub username: String,
    pub password: String,
    pub database: String,
    pub max_connections: u32,
    pub timeout: std::time::Duration,
    pub ssl: bool,
}

impl DatabaseConfig {
    pub fn new() -> DatabaseConfigBuilder {
        DatabaseConfigBuilder::default()
    }
}

#[derive(Default)]
pub struct DatabaseConfigBuilder {
    host: Option<String>,
    port: Option<u16>,
    username: Option<String>,
    password: Option<String>,
    database: Option<String>,
    max_connections: Option<u32>,
    timeout: Option<std::time::Duration>,
    ssl: Option<bool>,
}

impl DatabaseConfigBuilder {
    pub fn host(mut self, host: impl Into<String>) -> Self {
        self.host = Some(host.into());
        self
    }
    
    pub fn port(mut self, port: u16) -> Self {
        self.port = Some(port);
        self
    }
    
    pub fn username(mut self, username: impl Into<String>) -> Self {
        self.username = Some(username.into());
        self
    }
    
    pub fn password(mut self, password: impl Into<String>) -> Self {
        self.password = Some(password.into());
        self
    }
    
    pub fn database(mut self, database: impl Into<String>) -> Self {
        self.database = Some(database.into());
        self
    }
    
    pub fn max_connections(mut self, max_connections: u32) -> Self {
        self.max_connections = Some(max_connections);
        self
    }
    
    pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
        self.timeout = Some(timeout);
        self
    }
    
    pub fn ssl(mut self, ssl: bool) -> Self {
        self.ssl = Some(ssl);
        self
    }
    
    pub fn build(self) -> Result<DatabaseConfig, String> {
        Ok(DatabaseConfig {
            host: self.host.ok_or("Host is required")?,
            port: self.port.ok_or("Port is required")?,
            username: self.username.ok_or("Username is required")?,
            password: self.password.ok_or("Password is required")?,
            database: self.database.ok_or("Database is required")?,
            max_connections: self.max_connections.unwrap_or(10),
            timeout: self.timeout.unwrap_or_else(|| std::time::Duration::from_secs(30)),
            ssl: self.ssl.unwrap_or(false),
        })
    }
}

// 使用示例
fn main() -> Result<(), String> {
    let config = DatabaseConfig::new()
        .host("localhost")
        .port(5432)
        .username("user")
        .password("password")
        .database("mydb")
        .max_connections(20)
        .timeout(std::time::Duration::from_secs(60))
        .ssl(true)
        .build()?;
    
    println!("Database config: {:?}", config);
    Ok(())
}

策略模式

策略模式允许在运行时选择算法:

pub trait PaymentStrategy {
    fn pay(&self, amount: f64) -> Result<(), PaymentError>;
}

#[derive(Debug)]
pub enum PaymentError {
    InsufficientFunds,
    NetworkError,
    InvalidCard,
}

pub struct CreditCardPayment {
    card_number: String,
    cvv: String,
}

impl CreditCardPayment {
    pub fn new(card_number: String, cvv: String) -> Self {
        Self { card_number, cvv }
    }
}

impl PaymentStrategy for CreditCardPayment {
    fn pay(&self, amount: f64) -> Result<(), PaymentError> {
        println!("Processing credit card payment of ${:.2}", amount);
        // 模拟支付处理
        if amount > 1000.0 {
            Err(PaymentError::InsufficientFunds)
        } else {
            Ok(())
        }
    }
}

pub struct PayPalPayment {
    email: String,
}

impl PayPalPayment {
    pub fn new(email: String) -> Self {
        Self { email }
    }
}

impl PaymentStrategy for PayPalPayment {
    fn pay(&self, amount: f64) -> Result<(), PaymentError> {
        println!("Processing PayPal payment of ${:.2} to {}", amount, self.email);
        // 模拟支付处理
        Ok(())
    }
}

pub struct BankTransferPayment {
    account_number: String,
    routing_number: String,
}

impl BankTransferPayment {
    pub fn new(account_number: String, routing_number: String) -> Self {
        Self { account_number, routing_number }
    }
}

impl PaymentStrategy for BankTransferPayment {
    fn pay(&self, amount: f64) -> Result<(), PaymentError> {
        println!("Processing bank transfer of ${:.2}", amount);
        // 模拟支付处理
        Ok(())
    }
}

pub struct PaymentProcessor {
    strategy: Box<dyn PaymentStrategy>,
}

impl PaymentProcessor {
    pub fn new(strategy: Box<dyn PaymentStrategy>) -> Self {
        Self { strategy }
    }
    
    pub fn set_strategy(&mut self, strategy: Box<dyn PaymentStrategy>) {
        self.strategy = strategy;
    }
    
    pub fn process_payment(&self, amount: f64) -> Result<(), PaymentError> {
        self.strategy.pay(amount)
    }
}

// 使用示例
fn main() -> Result<(), PaymentError> {
    let credit_card = CreditCardPayment::new("1234-5678-9012-3456".to_string(), "123".to_string());
    let mut processor = PaymentProcessor::new(Box::new(credit_card));
    
    processor.process_payment(100.0)?;
    
    let paypal = PayPalPayment::new("user@example.com".to_string());
    processor.set_strategy(Box::new(paypal));
    
    processor.process_payment(200.0)?;
    
    Ok(())
}

观察者模式

观察者模式在Rust中可以通过trait和智能指针实现:

use std::sync::{Arc, Mutex};
use std::collections::HashMap;

pub trait Observer {
    fn update(&self, event: &Event);
}

#[derive(Debug, Clone)]
pub struct Event {
    pub event_type: String,
    pub data: String,
    pub timestamp: std::time::SystemTime,
}

impl Event {
    pub fn new(event_type: String, data: String) -> Self {
        Self {
            event_type,
            data,
            timestamp: std::time::SystemTime::now(),
        }
    }
}

pub struct EventBus {
    observers: Arc<Mutex<HashMap<String, Vec<Arc<dyn Observer + Send + Sync>>>>>,
}

impl EventBus {
    pub fn new() -> Self {
        Self {
            observers: Arc::new(Mutex::new(HashMap::new())),
        }
    }
    
    pub fn subscribe(&self, event_type: String, observer: Arc<dyn Observer + Send + Sync>) {
        let mut observers = self.observers.lock().unwrap();
        observers.entry(event_type).or_insert_with(Vec::new).push(observer);
    }
    
    pub fn publish(&self, event: Event) {
        let observers = self.observers.lock().unwrap();
        if let Some(observers_list) = observers.get(&event.event_type) {
            for observer in observers_list {
                observer.update(&event);
            }
        }
    }
}

// 具体的观察者实现
pub struct LogObserver {
    name: String,
}

impl LogObserver {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl Observer for LogObserver {
    fn update(&self, event: &Event) {
        println!("[{}] Event received: {:?}", self.name, event);
    }
}

pub struct EmailObserver {
    email: String,
}

impl EmailObserver {
    pub fn new(email: String) -> Self {
        Self { email }
    }
}

impl Observer for EmailObserver {
    fn update(&self, event: &Event) {
        println!("Sending email to {}: Event '{}' occurred", self.email, event.event_type);
    }
}

// 使用示例
fn main() {
    let event_bus = EventBus::new();
    
    let log_observer = Arc::new(LogObserver::new("Logger".to_string()));
    let email_observer = Arc::new(EmailObserver::new("admin@example.com".to_string()));
    
    event_bus.subscribe("user.login".to_string(), log_observer.clone());
    event_bus.subscribe("user.login".to_string(), email_observer.clone());
    event_bus.subscribe("user.logout".to_string(), log_observer.clone());
    
    // 发布事件
    event_bus.publish(Event::new("user.login".to_string(), "User 123 logged in".to_string()));
    event_bus.publish(Event::new("user.logout".to_string(), "User 123 logged out".to_string()));
}

工厂模式

工厂模式在Rust中可以通过trait和枚举实现:

pub trait Animal {
    fn make_sound(&self);
    fn get_name(&self) -> &str;
}

pub struct Dog {
    name: String,
}

impl Dog {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl Animal for Dog {
    fn make_sound(&self) {
        println!("{} says: Woof!", self.name);
    }
    
    fn get_name(&self) -> &str {
        &self.name
    }
}

pub struct Cat {
    name: String,
}

impl Cat {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl Animal for Cat {
    fn make_sound(&self) {
        println!("{} says: Meow!", self.name);
    }
    
    fn get_name(&self) -> &str {
        &self.name
    }
}

pub struct Bird {
    name: String,
}

impl Bird {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl Animal for Bird {
    fn make_sound(&self) {
        println!("{} says: Tweet!", self.name);
    }
    
    fn get_name(&self) -> &str {
        &self.name
    }
}

#[derive(Debug)]
pub enum AnimalType {
    Dog,
    Cat,
    Bird,
}

pub struct AnimalFactory;

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

// 使用示例
fn main() {
    let animals = vec![
        AnimalFactory::create_animal(AnimalType::Dog, "Buddy".to_string()),
        AnimalFactory::create_animal(AnimalType::Cat, "Whiskers".to_string()),
        AnimalFactory::create_animal(AnimalType::Bird, "Tweety".to_string()),
    ];
    
    for animal in animals {
        println!("Animal: {}", animal.get_name());
        animal.make_sound();
    }
}

单例模式

在Rust中实现单例模式需要小心处理:

use std::sync::{Arc, Mutex, Once};
use std::sync::atomic::{AtomicPtr, Ordering};

pub struct DatabaseConnection {
    connection_string: String,
}

impl DatabaseConnection {
    fn new(connection_string: String) -> Self {
        println!("Creating new database connection to: {}", connection_string);
        Self { connection_string }
    }
    
    pub fn execute_query(&self, query: &str) {
        println!("Executing query '{}' on connection to: {}", query, self.connection_string);
    }
}

// 使用Once和AtomicPtr实现线程安全的单例
pub struct DatabaseManager {
    connection: AtomicPtr<DatabaseConnection>,
    init: Once,
}

impl DatabaseManager {
    const fn new() -> Self {
        Self {
            connection: AtomicPtr::new(std::ptr::null_mut()),
            init: Once::new(),
        }
    }
    
    pub fn get_instance() -> &'static DatabaseManager {
        static INSTANCE: DatabaseManager = DatabaseManager::new();
        &INSTANCE
    }
    
    pub fn get_connection(&self) -> &DatabaseConnection {
        self.init.call_once(|| {
            let connection = Box::new(DatabaseConnection::new(
                "postgresql://localhost/mydb".to_string()
            ));
            self.connection.store(Box::into_raw(connection), Ordering::SeqCst);
        });
        
        unsafe {
            &*self.connection.load(Ordering::SeqCst)
        }
    }
}

// 使用示例
fn main() {
    let db_manager = DatabaseManager::get_instance();
    
    // 多次调用返回同一个实例
    let connection1 = db_manager.get_connection();
    let connection2 = db_manager.get_connection();
    
    connection1.execute_query("SELECT * FROM users");
    connection2.execute_query("SELECT * FROM posts");
    
    // 验证是同一个实例
    println!("Same instance: {}", std::ptr::eq(connection1, connection2));
}

装饰器模式

装饰器模式在Rust中可以通过trait和组合实现:

pub trait Coffee {
    fn cost(&self) -> f64;
    fn description(&self) -> String;
}

pub struct SimpleCoffee;

impl Coffee for SimpleCoffee {
    fn cost(&self) -> f64 {
        2.0
    }
    
    fn description(&self) -> String {
        "Simple coffee".to_string()
    }
}

pub struct CoffeeDecorator {
    coffee: Box<dyn Coffee>,
}

impl CoffeeDecorator {
    pub fn new(coffee: Box<dyn Coffee>) -> Self {
        Self { coffee }
    }
}

impl Coffee for CoffeeDecorator {
    fn cost(&self) -> f64 {
        self.coffee.cost()
    }
    
    fn description(&self) -> String {
        self.coffee.description()
    }
}

pub struct MilkDecorator {
    coffee: Box<dyn Coffee>,
}

impl MilkDecorator {
    pub fn new(coffee: Box<dyn Coffee>) -> Self {
        Self { coffee }
    }
}

impl Coffee for MilkDecorator {
    fn cost(&self) -> f64 {
        self.coffee.cost() + 0.5
    }
    
    fn description(&self) -> String {
        format!("{}, milk", self.coffee.description())
    }
}

pub struct SugarDecorator {
    coffee: Box<dyn Coffee>,
}

impl SugarDecorator {
    pub fn new(coffee: Box<dyn Coffee>) -> Self {
        Self { coffee }
    }
}

impl Coffee for SugarDecorator {
    fn cost(&self) -> f64 {
        self.coffee.cost() + 0.2
    }
    
    fn description(&self) -> String {
        format!("{}, sugar", self.coffee.description())
    }
}

pub struct WhipDecorator {
    coffee: Box<dyn Coffee>,
}

impl WhipDecorator {
    pub fn new(coffee: Box<dyn Coffee>) -> Self {
        Self { coffee }
    }
}

impl Coffee for WhipDecorator {
    fn cost(&self) -> f64 {
        self.coffee.cost() + 0.8
    }
    
    fn description(&self) -> String {
        format!("{}, whip", self.coffee.description())
    }
}

// 使用示例
fn main() {
    let coffee = Box::new(SimpleCoffee);
    let coffee_with_milk = Box::new(MilkDecorator::new(coffee));
    let coffee_with_milk_and_sugar = Box::new(SugarDecorator::new(coffee_with_milk));
    let coffee_with_milk_sugar_and_whip = Box::new(WhipDecorator::new(coffee_with_milk_and_sugar));
    
    println!("Description: {}", coffee_with_milk_sugar_and_whip.description());
    println!("Cost: ${:.2}", coffee_with_milk_sugar_and_whip.cost());
}

命令模式

命令模式在Rust中可以通过trait实现:

pub trait Command {
    fn execute(&self);
    fn undo(&self);
}

pub struct Light {
    is_on: bool,
}

impl Light {
    pub fn new() -> Self {
        Self { is_on: false }
    }
    
    pub fn turn_on(&mut self) {
        self.is_on = true;
        println!("Light is on");
    }
    
    pub fn turn_off(&mut self) {
        self.is_on = false;
        println!("Light is off");
    }
    
    pub fn is_on(&self) -> bool {
        self.is_on
    }
}

pub struct LightOnCommand {
    light: std::rc::Rc<std::cell::RefCell<Light>>,
}

impl LightOnCommand {
    pub fn new(light: std::rc::Rc<std::cell::RefCell<Light>>) -> Self {
        Self { light }
    }
}

impl Command for LightOnCommand {
    fn execute(&self) {
        self.light.borrow_mut().turn_on();
    }
    
    fn undo(&self) {
        self.light.borrow_mut().turn_off();
    }
}

pub struct LightOffCommand {
    light: std::rc::Rc<std::cell::RefCell<Light>>,
}

impl LightOffCommand {
    pub fn new(light: std::rc::Rc<std::cell::RefCell<Light>>) -> Self {
        Self { light }
    }
}

impl Command for LightOffCommand {
    fn execute(&self) {
        self.light.borrow_mut().turn_off();
    }
    
    fn undo(&self) {
        self.light.borrow_mut().turn_on();
    }
}

pub struct RemoteControl {
    commands: Vec<Box<dyn Command>>,
    undo_command: Option<Box<dyn Command>>,
}

impl RemoteControl {
    pub fn new() -> Self {
        Self {
            commands: Vec::new(),
            undo_command: None,
        }
    }
    
    pub fn set_command(&mut self, command: Box<dyn Command>) {
        self.commands.push(command);
    }
    
    pub fn press_button(&mut self, slot: usize) {
        if let Some(command) = self.commands.get(slot) {
            command.execute();
            // 保存命令用于撤销
            // 注意:这里简化了实现,实际中需要克隆命令
        }
    }
    
    pub fn press_undo(&mut self) {
        if let Some(command) = &self.undo_command {
            command.undo();
        }
    }
}

// 使用示例
fn main() {
    let light = std::rc::Rc::new(std::cell::RefCell::new(Light::new()));
    
    let mut remote = RemoteControl::new();
    remote.set_command(Box::new(LightOnCommand::new(light.clone())));
    remote.set_command(Box::new(LightOffCommand::new(light.clone())));
    
    remote.press_button(0); // 开灯
    remote.press_button(1); // 关灯
}

适配器模式

适配器模式在Rust中可以通过trait实现:

// 现有的接口
pub trait OldPrinter {
    fn print_old_format(&self, text: &str);
}

pub struct LegacyPrinter;

impl OldPrinter for LegacyPrinter {
    fn print_old_format(&self, text: &str) {
        println!("[LEGACY] {}", text);
    }
}

// 新的接口
pub trait NewPrinter {
    fn print(&self, text: &str);
    fn print_with_format(&self, text: &str, format: &str);
}

pub struct ModernPrinter;

impl NewPrinter for ModernPrinter {
    fn print(&self, text: &str) {
        println!("[MODERN] {}", text);
    }
    
    fn print_with_format(&self, text: &str, format: &str) {
        println!("[MODERN] [{}] {}", format, text);
    }
}

// 适配器
pub struct PrinterAdapter {
    legacy_printer: LegacyPrinter,
}

impl PrinterAdapter {
    pub fn new(legacy_printer: LegacyPrinter) -> Self {
        Self { legacy_printer }
    }
}

impl NewPrinter for PrinterAdapter {
    fn print(&self, text: &str) {
        self.legacy_printer.print_old_format(text);
    }
    
    fn print_with_format(&self, text: &str, format: &str) {
        // 将新格式转换为旧格式
        let formatted_text = format!("[{}] {}", format, text);
        self.legacy_printer.print_old_format(&formatted_text);
    }
}

// 使用示例
fn main() {
    let modern_printer = ModernPrinter;
    let legacy_printer = LegacyPrinter;
    let adapter = PrinterAdapter::new(legacy_printer);
    
    // 使用现代接口
    modern_printer.print("Hello from modern printer");
    modern_printer.print_with_format("Formatted text", "INFO");
    
    // 使用适配器
    adapter.print("Hello from legacy printer via adapter");
    adapter.print_with_format("Formatted text", "WARNING");
}

写在最后

Rust中的高级模式提供了:

  • 代码复用:通过模式避免重复代码
  • 灵活性:运行时选择不同的实现
  • 可维护性:清晰的代码结构和职责分离
  • 可扩展性:易于添加新功能
  • 类型安全:编译时检查模式实现的正确性

掌握这些模式不仅能让我们写出更优雅的Rust代码,还能提高代码的质量和可维护性。模式是软件工程中的重大工具,它们协助我们解决常见的设计问题,并提供了经过验证的解决方案。

© 版权声明

相关文章

暂无评论

none
暂无评论...