Rust设计模式

news2024/10/1 1:13:01

目录

  • 一、创建型
    • 单例模式
      • 懒汉式
      • 饿汉式
    • 工厂模式(工厂方法和抽象工厂)
      • 简单工厂模式
      • 工厂方法
      • 抽象工厂
    • 建造者模式
    • 原型模式
  • 二、结构型
    • 代理模式
    • 桥接模式
    • 装饰器模式
    • 适配器模式
    • 门面模式(外观模式)
    • 组合模式(部分整体模式)
    • 享元模式
  • 三、行为型
    • 观察者模式(发布订阅模式)
    • 模板模式
    • 策略模式
    • 责任链模式
    • 迭代器模式
    • 状态模式
    • 访问者模式
    • 备忘录模式
    • 命令模式
      • 使用trait
      • 使用函数指针
      • 使用Fn trait
    • 解释器模式
    • 中介模式

设计模式

设计模式(design pattern)是对软件设计中普遍存在的各种问题所提出的解决方案

  • 寻找变化点,然后在变化点应用设计模式
  • 重构获得模式(不应该为了模式而模式)

重构关键法

  • 静态->动态
  • 早绑定->晚绑定
  • 继承->组合
  • 编译时依赖->运行时依赖
  • 紧耦合->松耦合

代码质量标准

可维护性(maintainability):开发人员能够轻松地理解、修改和调试代码,以适应需求的变化或修复错误

可读性(readability):可读性好的代码使用清晰的命名、适当的注释和良好的代码风格,使得其他开发人员能够快速理解代码的意图和功能

可扩展性(extensibility):可扩展的代码设计考虑到未来的需求变化,通过模块化、低耦合和高内聚的设计,使得新增功能或修改现有功能变得容易

灵活性(flexibility):通过配置、参数化或拓展点来适应不同的环境或需求变化,而无需对核心代码进行大规模的修改

简洁性(simplicity):具有清晰的逻辑结构,没有冗余的部分,并且遵循简单直接的设计原则

可复用性(reusability):具有通用性和模块化的设计,可以在不同的项目或场景中被多次使用,从而减少开发时间和资源

可测试性(testability):具有良好的模块划分和依赖管理,使得单元测试、集成测试和自动化测试更容易实施,可测试的代码有助于发现和修复潜在的问题,并提供更高的代码质量

六大设计原则

SOLID原则

  • SRP(Single Responsibility Principle,单一职责原则) :一个类或者模块只负责完成一个职责(或者功能)。将功能分解为小而聚焦的组件,使得每个组件只负责特定的任务,从而提高代码的可维护性和可读性
  • OCP(Open-Closed Principle,开放封闭原则) :软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。在添加新功能时,应该通过扩展现有代码而不是修改现有代码来实现
  • LSP(Liskov Substitution Principle,里氏替换原则) :子类应该能够在不破坏程序正确性的前提下,替代父类在任何地方出现的实例。遵循里氏替换原则可以确保代码的稳定性和可靠性,并促进代码的重用性
  • ISP(Interface Segregation Principle,接口隔离原则) :客户端不应该依赖它不需要的接口。将接口细分为更小、更具体的部分,以减少对不相关功能的依赖,可以减少代码的耦合性,提高灵活性和可维护性
  • DIP(Dependency Inversion Principle,依赖倒置原则) :高层模块不应该依赖低层模块,它们都应该依赖于抽象。使用抽象(接口或抽象类)来定义模块之间的依赖关系,而不是依赖具体的实现细节。可以实现松耦合的设计,提高代码的可测试性和可扩展性

DRY原则(Don’t Repeat Yourself)

不要重复自己,不要写重复的代码

KISS原则(Keep It Simple and Stupid)

尽量保持简单

YAGNI原则(You Aren’t Gonna Need It)

你不会需要它,不要去设计当前用不到的功能;不要去编写当前用不到的代码

CRP原则(Composite Reuse Principle)

尽量使用对象组合而不是继承

虽然Rust没有继承的关键字,但可以在trait中定义默认方法实现继承;将trait作为struct的字段或struct实现多个trait可以实现组合

LOD法则(Law of Demeter)

一个软件实体应当尽可能少的与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少的影响其他的模块,扩展会相对容易

23种设计模式分类

创建型

单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式、原型模式

结构型

代理模式、桥接模式、装饰者模式、适配器模式、门面模式、组合模式、享元模式

行为型

观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式、访问者模式、备忘录模式、命令模式、解释器模式、中介模式

一、创建型

单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式、原型模式

单例模式

确保一个对象只有一个实例

标准库实现懒汉式

use std::sync::{Once, Arc, Mutex};

struct Singleton {
    value: i32,
}
impl Singleton {
    // 初始化唯一的实例
    fn new() -> Self {
        Singleton { value: 0 }
    }
    // 获取单例实例
    fn get_instance() -> Arc<Mutex<Singleton>> {
        static mut INSTANCE: Option<Arc<Mutex<Singleton>>> = None;
        static ONCE: Once = Once::new();

        unsafe {
            ONCE.call_once(|| {// 确保只初始化一次
                let singleton = Singleton::new();
                INSTANCE = Some(Arc::new(Mutex::new(singleton)));
            });
            INSTANCE.clone().unwrap()
        }
    }
    // 设置值
    fn set_value(&mut self, value: i32) {
        self.value = value;
    }
    // 获取值
    fn get_value(&self) -> i32 {
        self.value
    }
}

fn main() {
    // 获取单例实例并设置值
    let singleton = Singleton::get_instance();
    {
        let mut s = singleton.lock().unwrap();
        s.set_value(42);
    }
    // 获取单例实例并获取值
    {
        let s = singleton.lock().unwrap();
        println!("Singleton value: {}", s.get_value());
    }
}
懒汉式

在第一次需要时才进行初始化

需要第三方库lazy_static = "1.5.0"

use std::sync::{Arc, Mutex};
use lazy_static::lazy_static;

struct Singleton {
    value: i32,
}
impl Singleton {
    fn new() -> Self {
        Singleton { value: 0 }
    }
    fn get_instance() -> Arc<Mutex<Singleton>> {
        lazy_static! {// 惰性初始化全局静态变量 INSTANCE
            // Arc共享所有权
            static ref INSTANCE: Arc<Mutex<Singleton>> = Arc::new(Mutex::new(Singleton::new()));
        }
        Arc::clone(&INSTANCE)
    }

    fn set_value(&mut self, value: i32) {
        self.value = value;
    }

    fn get_value(&self) -> i32 {
        self.value
    }
}

fn main() {
    // 获取单例实例并设置值
    let singleton = Singleton::get_instance();
    {
        let mut s = singleton.lock().unwrap();
        s.set_value(42);
    }
    // 获取单例实例并获取值
    {
        let s = singleton.lock().unwrap();
        println!("Singleton value: {}", s.get_value());
    }
}
饿汉式

在程序启动时就创建单例实例

需要第三方库once_cell = "1.19.0"

use std::sync::{Arc, Mutex};
use std::sync::OnceLock;

struct Singleton {
    value: i32,
}
impl Singleton {
    fn new() -> Self {
        Singleton { value: 0 }
    }
    fn get_instance() -> Arc<Mutex<Singleton>> {
        // 在程序启动时即初始化
        static INSTANCE: OnceLock<Arc<Mutex<Singleton>>> = OnceLock::new();
        INSTANCE.get_or_init(|| Arc::new(Mutex::new(Singleton::new()))).clone()
    }
    fn set_value(&mut self, value: i32) {
        self.value = value;
    }
    fn get_value(&self) -> i32 {
        self.value
    }
}
fn main() {
    // 获取单例实例并设置值
    let singleton = Singleton::get_instance();
    {
        let mut s = singleton.lock().unwrap();
        s.set_value(42);
    }
    // 获取单例实例并获取值
    {
        let s = singleton.lock().unwrap();
        println!("Singleton value: {}", s.get_value());
    }
}

工厂模式(工厂方法和抽象工厂)

简单工厂模式

根据传入的参数决定创建哪种类型的对象

// 产品trait
trait Product {
    fn use_product(&self);
}

// 具体产品A
struct ConcreteProductA;
impl Product for ConcreteProductA {
    fn use_product(&self) {
        println!("Using ConcreteProductA");
    }
}

// 具体产品B
struct ConcreteProductB;
impl Product for ConcreteProductB {
    fn use_product(&self) {
        println!("Using ConcreteProductB");
    }
}

// 简单工厂
struct SimpleFactory;
impl SimpleFactory {
    fn create_product(product_type: &str) -> Box<dyn Product> {
        match product_type {
            "A" => Box::new(ConcreteProductA),
            "B" => Box::new(ConcreteProductB),
            _ => panic!("Unknown product type"),
        }
    }
}
fn main() {
    // 使用简单工厂创建产品A
    let product_a = SimpleFactory::create_product("A");
    product_a.use_product();

    // 使用简单工厂创建产品B
    let product_b = SimpleFactory::create_product("B");
    product_b.use_product();
}
工厂方法

定义创建对象的接口,将创建对象延迟到具体产品实现

// 产品trait
trait Product {
    fn use_product(&self);
}

// 具体产品A
struct ConcreteProductA;
impl Product for ConcreteProductA {
    fn use_product(&self) {
        println!("Using ConcreteProductA");
    }
}

// 具体产品B
struct ConcreteProductB;
impl Product for ConcreteProductB {
    fn use_product(&self) {
        println!("Using ConcreteProductB");
    }
}

// 工厂接口
trait Factory {
    fn create_product(&self) -> Box<dyn Product>;
}

// 具体工厂A
struct ConcreteFactoryA;
impl Factory for ConcreteFactoryA {
    fn create_product(&self) -> Box<dyn Product> {
        Box::new(ConcreteProductA)
    }
}

// 具体工厂B
struct ConcreteFactoryB;
impl Factory for ConcreteFactoryB {
    fn create_product(&self) -> Box<dyn Product> {
        Box::new(ConcreteProductB)
    }
}

fn main() {
    let factory_a: Box<dyn Factory> = Box::new(ConcreteFactoryA);
    let product_a = factory_a.create_product();
    product_a.use_product();

    let factory_b: Box<dyn Factory> = Box::new(ConcreteFactoryB);
    let product_b = factory_b.create_product();
    product_b.use_product();
}
抽象工厂

创建一系列trait,通过trait创建相关依赖的对象

  • 需要在不同条件下创建实例时使用
// 抽象产品
trait AbstractProductA {
    fn feature_a(&self);
}
trait AbstractProductB {
    fn feature_b(&self);
}

// 具体产品
struct ConcreteProductA1;
struct ConcreteProductA2;
struct ConcreteProductB1;
struct ConcreteProductB2;

impl AbstractProductA for ConcreteProductA1 {
    fn feature_a(&self) {
        println!("Feature A1");
    }
}

impl AbstractProductA for ConcreteProductA2 {
    fn feature_a(&self) {
        println!("Feature A2");
    }
}

impl AbstractProductB for ConcreteProductB1 {
    fn feature_b(&self) {
        println!("Feature B1");
    }
}

impl AbstractProductB for ConcreteProductB2 {
    fn feature_b(&self) {
        println!("Feature B2");
    }
}

// 抽象工厂
trait AbstractFactory {
    fn create_product_a(&self) -> Box<dyn AbstractProductA>;
    fn create_product_b(&self) -> Box<dyn AbstractProductB>;
}

// 具体工厂
struct ConcreteFactory1;
impl AbstractFactory for ConcreteFactory1 {
    fn create_product_a(&self) -> Box<dyn AbstractProductA> {
        Box::new(ConcreteProductA1)
    }
    fn create_product_b(&self) -> Box<dyn AbstractProductB> {
        Box::new(ConcreteProductB1)
    }
}

struct ConcreteFactory2;
impl AbstractFactory for ConcreteFactory2 {
    fn create_product_a(&self) -> Box<dyn AbstractProductA> {
        Box::new(ConcreteProductA2)
    }
    fn create_product_b(&self) -> Box<dyn AbstractProductB> {
        Box::new(ConcreteProductB2)
    }
}

fn main() {
    let factory1: Box<dyn AbstractFactory> = Box::new(ConcreteFactory1);
    let product_a1 = factory1.create_product_a();
    let product_b1 = factory1.create_product_b();
    product_a1.feature_a();
    product_b1.feature_b();

    let factory2: Box<dyn AbstractFactory> = Box::new(ConcreteFactory2);
    let product_a2 = factory2.create_product_a();
    let product_b2 = factory2.create_product_b();
    product_a2.feature_a();
    product_b2.feature_b();
}

建造者模式

将一个复杂对象的构建过程与其表示相分离,从而可以创建具有不同表示形式的对象

// 产品
struct Product {
    part_a: String,
    part_b: String,
    part_c: String,
}

// 建造者接口
trait Builder {
    fn build_part_a(&mut self);
    fn build_part_b(&mut self);
    fn build_part_c(&mut self);
    fn get_result(&self) -> &Product;
}

// 具体建造者
struct ConcreteBuilder {
    product: Product,
}
impl ConcreteBuilder {
    fn new() -> Self {
        ConcreteBuilder {
            product: Product {
                part_a: String::new(),
                part_b: String::new(),
                part_c: String::new(),
            },
        }
    }
}

impl Builder for ConcreteBuilder {
    fn build_part_a(&mut self) {
        self.product.part_a = String::from("Part A");
    }
    fn build_part_b(&mut self) {
        self.product.part_b = String::from("Part B");
    }
    fn build_part_c(&mut self) {
        self.product.part_c = String::from("Part C");
    }
    fn get_result(&self) -> &Product {
        &self.product
    }
}

// 指挥者
struct Director;
impl Director {
    fn construct(builder: &mut dyn Builder) {
        builder.build_part_a();
        builder.build_part_b();
        builder.build_part_c();
    }
}
fn main() {
    let mut builder = ConcreteBuilder::new();
    Director::construct(&mut builder);
    let product = builder.get_result();
    println!("Product: {}, {}, {}", product.part_a, product.part_b, product.part_c);
}

原型模式

通过复制现有对象来创建新对象,而不是通过实例化类来创建对象

#[derive(Clone)]
struct Prototype {
    field: String,
}
impl Prototype {
    fn new(field: &str) -> Self {
        Prototype {
            field: field.to_string(),
        }
    }
    fn get_field(&self) -> &str {
        &self.field
    }
}
fn main() {
    let original = Prototype::new("Original");
    let clone = original.clone();
    
    println!("Original: {}", original.get_field());
    println!("Clone: {}", clone.get_field());
}

二、结构型

代理模式、桥接模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式

代理模式

通过代理中间层来访问真正的对象

// 被代理的对象
struct RealSubject;

impl RealSubject {
    fn request(&self) {
        println!("RealSubject: Handling request.");
    }
}

// 代理对象
struct Proxy {
    real_subject: RealSubject,
}

impl Proxy {
    fn new() -> Self {
        Proxy {
            real_subject: RealSubject,
        }
    }
    fn request(&self) {
        println!("Proxy: Before calling RealSubject.");
        self.real_subject.request();
        println!("Proxy: After calling RealSubject.");
    }
}

fn main() {
    let proxy = Proxy::new();
    proxy.request();
}

桥接模式

将抽象与实现解耦,使其独立变化

// 将抽象和实现连接起来
trait Implementor {
    fn operation_impl(&self) -> String;
}

// 具体实现
struct ConcreteImplementorA;

impl Implementor for ConcreteImplementorA {
    fn operation_impl(&self) -> String {
        "ConcreteImplementorA".to_string()
    }
}
// 具体实现
struct ConcreteImplementorB;

impl Implementor for ConcreteImplementorB {
    fn operation_impl(&self) -> String {
        "ConcreteImplementorB".to_string()
    }
}

// 抽象部分
struct Abstraction<I: Implementor> {
    implementor: I,
}

impl<I: Implementor> Abstraction<I> {
    fn new(implementor: I) -> Self {
        Abstraction { implementor }
    }

    fn operation(&self) -> String {
        format!("Abstraction({})", self.implementor.operation_impl())
    }
}

fn main() {
    let implementor_a = ConcreteImplementorA;
    let implementor_b = ConcreteImplementorB;

    let abstraction_a = Abstraction::new(implementor_a);
    let abstraction_b = Abstraction::new(implementor_b);

    println!("{}", abstraction_a.operation());
    println!("{}", abstraction_b.operation());
}

装饰器模式

允许向一个现有的对象添加新的功能,同时又不改变其结构

// 定义一个 trait,表示基本的组件
trait Component {
    fn operation(&self) -> String;
}
// 具体组件实现
struct ConcreteComponent;
impl Component for ConcreteComponent {
    fn operation(&self) -> String {
        "ConcreteComponent".to_string()
    }
}
// 装饰器结构体
struct Decorator<T: Component> {
    component: T,
}
impl<T: Component> Component for Decorator<T> {
    fn operation(&self) -> String {
        // 在这里可以添加装饰器的功能
        format!("Decorator({})", self.component.operation())
    }
}
// 具体装饰器
struct ConcreteDecoratorA<T: Component> {
    component: T,
}
impl<T: Component> Component for ConcreteDecoratorA<T> {
    fn operation(&self) -> String {
        // 在装饰器中添加额外的行为
        format!("ConcreteDecoratorA({})", self.component.operation())
    }
}
fn main() {
    let component = ConcreteComponent;

    let decorated_component = Decorator { component };
    // 装饰功能
    let final_decorated = ConcreteDecoratorA { component: decorated_component };

    println!("{}", final_decorated.operation());
}

适配器模式

将一个接口转换为客户端所期望的接口,以便使得不兼容的接口能够一起工作

// 目标接口
trait Target {
    fn request(&self);
}

// 适配者
struct Adaptee;

impl Adaptee {
    fn specific_request(&self) {
        println!("Adaptee: Specific request.");
    }
}

// 适配器
struct Adapter {
    adaptee: Adaptee,
}

impl Target for Adapter {
    fn request(&self) {
        println!("Adapter: Adapting request.");
        // 适配
        self.adaptee.specific_request();
    }
}

fn main() {
    let adaptee = Adaptee;
    let adapter = Adapter { adaptee };
    // 通过适配器调用适配者的方法
    adapter.request();
}

门面模式(外观模式)

隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口

struct SubsystemA;

impl SubsystemA {
    fn operation_a(&self) {
        println!("SubsystemA: Operation A.");
    }
}

struct SubsystemB;

impl SubsystemB {
    fn operation_b(&self) {
        println!("SubsystemB: Operation B.");
    }
}

// 门面
struct Facade {
    subsystem_a: SubsystemA,
    subsystem_b: SubsystemB,
}

impl Facade {
    fn new() -> Self {
        Facade {
            subsystem_a: SubsystemA,
            subsystem_b: SubsystemB,
        }
    }

    fn operation(&self) {
        println!("Facade: Coordinating operations.");
        self.subsystem_a.operation_a();
        self.subsystem_b.operation_b();
    }
}

fn main() {
    let facade = Facade::new();
    facade.operation();
}

组合模式(部分整体模式)

把一组相似的对象当作一个单一的对象,将对象组合成树形结构,以表示部分和整体的层次关系

trait Component {
    fn operation(&self) -> String;
}
// 部分
struct Leaf {
    name: String,
}

impl Component for Leaf {
    fn operation(&self) -> String {
        format!("Leaf: {}", self.name)
    }
}
// 组合
struct Composite {
    children: Vec<Box<dyn Component>>,
}

impl Component for Composite {
    fn operation(&self) -> String {
        let mut result = "Composite:\n".to_string();
        for child in &self.children {
            result += &format!("  {}\n", child.operation());
        }
        result
    }
}

fn main() {
    let leaf1 = Leaf { name: "Leaf1".to_string() };
    let leaf2 = Leaf { name: "Leaf2".to_string() };
    
    let mut composite = Composite { children: vec![] };
    composite.children.push(Box::new(leaf1));
    composite.children.push(Box::new(leaf2));
    
    println!("{}", composite.operation());
}

享元模式

通过共享对象来减少内存使用

use std::collections::HashMap;
// 享元对象
struct Flyweight {
    intrinsic_state: String,
}

impl Flyweight {
    fn new(intrinsic_state: String) -> Self {
        Flyweight { intrinsic_state }
    }
    fn operation(&self, extrinsic_state: &str) {
        println!("Flyweight: {} - {}", self.intrinsic_state, extrinsic_state);
    }
}
// 享元工厂
struct FlyweightFactory {
    flyweights: HashMap<String, Flyweight>,
}

impl FlyweightFactory {
    fn new() -> Self {
        FlyweightFactory { flyweights: HashMap::new() }
    }
    fn get_flyweight(&mut self, key: &str) -> &Flyweight {
        self.flyweights.entry(key.to_string()).or_insert_with(|| Flyweight::new(key.to_string()))
    }
}

fn main() {
    let mut factory = FlyweightFactory::new();

    let flyweight1 = factory.get_flyweight("A");
    flyweight1.operation("First call");

    let flyweight2 = factory.get_flyweight("A");
    flyweight2.operation("Second call");
}

三、行为型

观察者模式、模板模式、责任链模式、迭代器模式、状态模式、访问者模式、备忘录模式、命令模式、解释器模式、中介模式

观察者模式(发布订阅模式)

一个对象的状态发生改变,所有的依赖对象都将得到通知

use std::collections::HashMap;

#[derive(Default)]
pub struct Editor {
    publisher: Publisher,
    file_path: String,
}

impl Editor {
    pub fn events(&mut self) -> &mut Publisher {
        &mut self.publisher
    }

    pub fn load(&mut self, path: String) {
        self.file_path = path.clone();
        self.publisher.notify(Event::Load, path);
    }

    pub fn save(&self) {
        self.publisher.notify(Event::Save, self.file_path.clone());
    }
}
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum Event {
    Load,
    Save,
}

// 订阅者
pub type Subscriber = fn(file_path: String);

// 发布者发布事件
#[derive(Default)]
pub struct Publisher {
    events: HashMap<Event, Vec<Subscriber>>,
}

impl Publisher {
    pub fn subscribe(&mut self, event_type: Event, listener: Subscriber) {
        self.events.entry(event_type.clone()).or_default();
        self.events.get_mut(&event_type).unwrap().push(listener);
    }

    pub fn unsubscribe(&mut self, event_type: Event, listener: Subscriber) {
        self.events
            .get_mut(&event_type)
            .unwrap()
            .retain(|&x| x != listener);
    }

    pub fn notify(&self, event_type: Event, file_path: String) {
        let listeners = self.events.get(&event_type).unwrap();
        for listener in listeners {
            listener(file_path.clone());
        }
    }
}
fn main() {
    let mut editor = Editor::default();

    editor.events().subscribe(Event::Load, |file_path| {
        let log = "/path/to/log/file.txt".to_string();
        println!("Save log to {}: Load file {}", log, file_path);
    });

    editor.events().subscribe(Event::Save, save_listener);

    editor.load("test1.txt".into());
    editor.load("test2.txt".into());
    editor.save();

    editor.events().unsubscribe(Event::Save, save_listener);
    editor.save();
}
// 具体订阅者
fn save_listener(file_path: String) {
    let email = "admin@example.com".to_string();
    println!("Email to {}: Save file {}", email, file_path);
}

模板模式

定义执行的稳定模板,将步骤延迟到实现

trait Template {
    fn step1(&self);// 变化的部分
    fn step2(&self);
    fn step3(&self);
    // 延迟到实现
    fn template_method(&self) {// 稳定的部分
        self.step1();
        self.step2();
        self.step3();
    }
}

struct ConcreteImplementation1 {
    // 可以包含特定于这个实现的状态
}

impl Template for ConcreteImplementation1 {
    fn step1(&self) {
        println!("ConcreteImplementation1: Step 1");
    }

    fn step2(&self) {
        println!("ConcreteImplementation1: Step 2");
    }

    fn step3(&self) {
        println!("ConcreteImplementation1: Step 3");
    }
}

struct ConcreteImplementation2 {
    // 可以包含特定于这个实现的状态
}

impl Template for ConcreteImplementation2 {
    fn step1(&self) {
        println!("ConcreteImplementation2: Step 1");
    }

    fn step2(&self) {
        println!("ConcreteImplementation2: Step 2");
    }

    fn step3(&self) {
        println!("ConcreteImplementation2: Step 3");
    }
}

fn main() {
    let implementation1 = ConcreteImplementation1 {};
    implementation1.template_method();

    let implementation2 = ConcreteImplementation2 {};
    implementation2.template_method();
}

策略模式

实现的行为和算法可以在运行时更改

trait Strategy {
    fn execute(&self);
}

struct ConcreteStrategyA;
impl Strategy for ConcreteStrategyA {
    fn execute(&self) {
        println!("Executing strategy A");
    }
}

struct ConcreteStrategyB;
impl Strategy for ConcreteStrategyB {
    fn execute(&self) {
        println!("Executing strategy B");
    }
}
// 维护对策略对象,将请求委派给具体策略对象
struct Context {
    strategy: Box<dyn Strategy>,
}
impl Context {
    fn new(strategy: Box<dyn Strategy>) -> Self {
        Context { strategy }
    }
    fn execute_strategy(&self) {
        self.strategy.execute();
    }
}

fn main() {
    let strategy_a = Box::new(ConcreteStrategyA {});
    // 多态调用
    let context_a = Context::new(strategy_a);
    context_a.execute_strategy();

    let strategy_b = Box::new(ConcreteStrategyB {});
    // 多态调用
    let context_b = Context::new(strategy_b);
    context_b.execute_strategy();
}

计算税种案例

// 抽象策略
trait TaxCalculationStrategy {
    fn calculate_tax(&self, income: f64) -> f64;
}
struct USTaxStrategy;
// 美国税
impl TaxCalculationStrategy for USTaxStrategy {
    fn calculate_tax(&self, income: f64) -> f64 {
        // 假设美国的税收计算逻辑
        if income <= 10000.0 {
            return income * 0.1;
        } else {
            return income * 0.15;
        }
    }
}
struct ChinaTaxStrategy;
// 中国税
impl TaxCalculationStrategy for ChinaTaxStrategy {
    fn calculate_tax(&self, income: f64) -> f64 {
        // 假设中国的税收计算逻辑
        if income <= 5000.0 {
            return 0.0;
        } else if income <= 8000.0 {
            return (income - 5000.0) * 0.03;
        } else {
            return income * 0.1;
        }
    }
}
struct JapanTaxStrategy;
// 日本税
impl TaxCalculationStrategy for JapanTaxStrategy {
    fn calculate_tax(&self, income: f64) -> f64 {
        // 假设日本的税收计算逻辑
        if income <= 20000.0 {
            return income * 0.05;
        } else {
            return income * 0.1;
        }
    }
}
// 上下文,稳定的部分
struct TaxCalculator {
    strategy: Box<dyn TaxCalculationStrategy>,
}
impl TaxCalculator {
    fn new(strategy: Box<dyn TaxCalculationStrategy>) -> Self {
        TaxCalculator { strategy }
    }

    fn calculate_tax(&self, income: f64) -> f64 {
        self.strategy.calculate_tax(income)
    }
}

fn main() {
    let us_calculator = TaxCalculator::new(Box::new(USTaxStrategy {}));
    let china_calculator = TaxCalculator::new(Box::new(ChinaTaxStrategy {}));
    let japan_calculator = TaxCalculator::new(Box::new(JapanTaxStrategy {}));

    let income = 15000.0;
    // 多态调用
    println!("US tax for income {}: {}", income, us_calculator.calculate_tax(income));
    println!("China tax for income {}: {}", income, china_calculator.calculate_tax(income));
    println!("Japan tax for income {}: {}", income, japan_calculator.calculate_tax(income));
}

责任链模式

为请求创建一个接收者对象的链,对请求的发送者和接收者进行解耦

#[derive(Default)]
pub struct Patient {
    pub name: String,
    pub registration_done: bool,
    pub doctor_check_up_done: bool,
    pub medicine_done: bool,
    pub payment_done: bool,
}
// 部门公共方法
trait Department {
    fn execute(&mut self, patient: &mut Patient) {
        self.handle(patient);
        if let Some(next) = self.next() {
            next.execute(patient);
        }
    }

    fn handle(&mut self, patient: &mut Patient);
    fn next(&mut self) -> Option<&mut Box<dyn Department>>;
}
// 收银
#[derive(Default)]
struct Cashier {
    next: Option<Box<dyn Department>>,
}

impl Department for Cashier {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.payment_done {
            println!("付款完成 {}", patient.name);
        } else {
            println!("付款中{}", patient.name);
            patient.payment_done = true;
        }
    }

    fn next(&mut self) -> Option<&mut Box<dyn Department>> {
        self.next.as_mut()
    }
}
// 医生
struct Doctor {
    next: Option<Box<dyn Department>>,
}

impl Doctor {
    pub fn new(next: Option<Box<dyn Department>>) -> Self {
        Self { next }
    }
}

impl Department for Doctor {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.doctor_check_up_done {
            println!("检查完成 {}", patient.name);
        } else {
            println!("检查中 {}", patient.name);
            patient.doctor_check_up_done = true;
        }
    }

    fn next(&mut self) -> Option<&mut Box<dyn Department>> {
        self.next.as_mut()
    }
}
// 药房
struct Medical {
    next: Option<Box<dyn Department>>,
}

impl Medical {
    pub fn new(next: Option<Box<dyn Department>>) -> Self {
        Self { next }
    }
}

impl Department for Medical {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.medicine_done {
            println!("取药完成 {}", patient.name);
        } else {
            println!("取药中 {}", patient.name);
            patient.medicine_done = true;
        }
    }

    fn next(&mut self) -> Option<&mut Box<dyn Department>> {
        self.next.as_mut()
    }
}
// 门诊
struct Reception {
    next: Option<Box<dyn Department>>,
}

impl Reception {
    pub fn new(next: Option<Box<dyn Department>>) -> Self {
        Self { next }
    }
}

impl Department for Reception {
    fn handle(&mut self, patient: &mut Patient) {
        if patient.registration_done {
            println!("挂号完成 {}", patient.name);
        } else {
            println!("挂号 {}", patient.name);
            patient.registration_done = true;
        }
    }

    fn next(&mut self) -> Option<&mut Box<dyn Department>> {
        self.next.as_mut()
    }
}

fn main() {
    let cashier = Box::new(Cashier::default());
    // 取药后收银
    let medical = Box::new(Medical::new(Some(cashier)));
    // 医生检查后取药
    let doctor = Box::new(Doctor::new(Some(medical)));
    // 挂号后医生检查
    let mut reception = Reception::new(Some(doctor));

    let mut patient = Patient {
        name: "张三".into(),
        ..Patient::default()
    };

    reception.execute(&mut patient);

    println!("\n看病处理:\n");
    reception.execute(&mut patient);
}

迭代器模式

提供顺序访问元素的方式

struct Iterator {
    index: usize,
    data: Vec<i32>,
}

impl Iterator {
    fn new(data: Vec<i32>) -> Self {
        Iterator { index: 0, data }
    }
    fn next(&mut self) -> Option<i32> {
        if self.index < self.data.len() {
            let value = self.data[self.index];
            self.index += 1;
            Some(value)
        } else {
            None
        }
    }
}
fn main() {
    let data = vec![1, 2, 3, 4];
    let mut iterator = Iterator::new(data);

    while let Some(value) = iterator.next() {
        println!("{}", value);
    }
}

状态模式

对象的行为基于状态改变

trait State {
    fn handle(&self);
}

struct Context {
    state: Box<dyn State>,
}
impl Context {
    fn new(state: Box<dyn State>) -> Self {
        Context { state }
    }
    fn set_state(&mut self, state: Box<dyn State>) {
        self.state = state;
    }
    fn request(&self) {
        self.state.handle();
    }
}

struct ConcreteStateA;
impl State for ConcreteStateA {
    fn handle(&self) {
        println!("Handling State A");
    }
}

struct ConcreteStateB;
impl State for ConcreteStateB {
    fn handle(&self) {
        println!("Handling State B");
    }
}
struct ConcreteStateC;
impl State for ConcreteStateC {
    fn handle(&self) {
        println!("Handling State C");
    }
}
fn main() {
    let mut context = Context::new(Box::new(ConcreteStateA));
    context.request();
    // 切换状态
    context.set_state(Box::new(ConcreteStateB));
    context.request();
    // 切换状态
    context.set_state(Box::new(ConcreteStateC));
    context.request();
}

访问者模式

在不改变元素类的情况下定义新的操作,元素对象接收访问者对象,访问者就可以处理元素对象上的操作

trait Visitor {
    fn visit_element_a(&self, element: &ElementA);
    fn visit_element_b(&self, element: &ElementB);
}

trait Element {
    fn accept(&self, visitor: &dyn Visitor);
}

struct ElementA;
impl Element for ElementA {
    fn accept(&self, visitor: &dyn Visitor) {
        visitor.visit_element_a(self);
    }
}

struct ElementB;
impl Element for ElementB {
    fn accept(&self, visitor: &dyn Visitor) {
        visitor.visit_element_b(self);
    }
}
// 具体访问者
struct ConcreteVisitor;
// 添加额外的功能
impl Visitor for ConcreteVisitor {
    fn visit_element_a(&self, _element: &ElementA) {
        println!("Visiting Element A");
    }

    fn visit_element_b(&self, _element: &ElementB) {
        println!("Visiting Element B");
    }
}

fn main() {
    let element_a = ElementA;
    let element_b = ElementB;
    let visitor = ConcreteVisitor;
    // 接收访问者对象
    element_a.accept(&visitor);
    element_b.accept(&visitor);
}

备忘录模式

保存对象的状态,以便后续恢复

#[derive(Clone)]
// 备忘录
struct Memento {
    state: String,
}
// 发起者
struct Originator {
    state: String,
}

impl Originator {
    fn new(state: String) -> Self {
        Originator { state }
    }
    // 存储状态
    fn create_memento(&self) -> Memento {
        Memento { state: self.state.clone() }
    }
    // 恢复状态
    fn restore(&mut self, memento: Memento) {
        self.state = memento.state;
    }
}

fn main() {
    let mut originator = Originator::new("State1".to_string());
    let memento = originator.create_memento();

    originator.restore(memento);
    println!("Restored state: {}", originator.state);
}

命令模式

将请求封装成对象,从而允许参数化客户和请求

trait Command {
    fn execute(&mut self);
}
// 接收者
struct Light {
    is_on: bool,
}
impl Light {
    // 执行关灯命令
    fn toggle(&mut self) {
        self.is_on =!self.is_on;
        println!("Light is now {}", if self.is_on { "ON" } else { "OFF" });
    }
}
// 调用者
struct ToggleCommand<'a> {
    light: &'a mut Light,
}
impl<'a> Command for ToggleCommand<'a> {
    //发送命令
    fn execute(&mut self) {
        self.light.toggle();
    }
}

fn main() {
    let mut light = Light { is_on: false };

    let mut command = ToggleCommand { light: &mut light };
    command.execute();

    let mut command = ToggleCommand { light: &mut light }; 
    command.execute();
}

以下数据库迁移的例子,创建了两个命令实例,执行和回滚的方法

使用trait
fn main(){
    let mut schema = Schema::new();
    // 建表动作
    let cmd = Box::new(CreateTable);
    schema.add_migration(cmd);
    // 添加字段动作
    let cmd = Box::new(AddField);
    schema.add_migration(cmd);
    assert_eq!(vec!["create table","add field"],schema.execute());
    assert_eq!(vec!["remove field","drop table"],schema.rollback());
}
// 定义trait封装两个方法,所有实现了这个迁移trait的必须实现这两个方法
pub trait Migration{
    fn execute(&self)->&str;
    fn rollback(&self)->&str;
}
// 定义创建表的结构体并实现Migration这个trait
pub struct CreateTable;
impl Migration for CreateTable{
    fn execute(&self)->&str{
        "create table"
    }
    fn rollback(&self)->&str{
        "drop table"
    }
}
// 定义添加字段的结构体并实现Migration这个trait
pub struct AddField;
impl Migration for AddField{
    fn execute(&self)->&str{
        "add field"
    }
    fn rollback(&self)->&str {
        "remove field"
    }
}
// 定义操作的命令并实现
struct Schema{
    commands:Vec<Box<dyn Migration>>,
}
impl Schema{
    // 接受新命令
    fn new()->Self{
        Self{
            commands:vec![]
        }
    }
    fn execute(&self)->Vec<&str>{
        self.commands.iter().map(|cmd|cmd.execute()).collect()
    }
    fn rollback(&self)->Vec<&str>{
        self.commands
        .iter()// 遍历
        .rev()// 反转
        .map(|cmd|cmd.rollback())// 对每个命令迭代
        .collect()// 将操作后的元素搜集为新的Vec
    }
    fn add_migration(&mut self,cmd:Box<dyn Migration>){
        self.commands.push(cmd);
    }
}
使用函数指针
fn main(){
    let mut schema = Schema::new();
    // 使用闭包
    schema.add_migration(||"create table".to_string(),||"drop table".to_string());
    // 使用函数
    schema.add_migration(add_field,remove_field);
    // 使用命令
    assert_eq!(vec!["create table","add field"],schema.execute());
    assert_eq!(vec!["remove field","drop table"],schema.rollback());
}
// 
type FnPtr=fn()->String;
// 定义命令
struct Command{
    execute:FnPtr,
    rollback:FnPtr,
}
// 存储迁移命令
struct Schema{
    commands:Vec<Command>,
}
impl Schema{
    fn new()->Self{
        Self { commands: vec![] }
    }
    fn add_migration(&mut self,execute:FnPtr,rollback:FnPtr){
        self.commands.push(Command{execute,rollback});
    }
    fn execute(&self)->Vec<String>{
        self.commands.iter().map(|cmd|(cmd.execute)()).collect()
    }
    fn rollback(&self)->Vec<String>{
        self.commands
        .iter()
        .rev()
        .map(|cmd|(cmd.rollback)())
        .collect()
    }
}

fn add_field()->String{
    "add field".to_string()
}
fn remove_field()->String{
    "remove field".to_string()
}
使用Fn trait

动态派发

Fn可以多次不可变调用闭包

fn main(){
    let mut schema = Schema::new();
    // 使用闭包
    schema.add_migration(||"create table".to_string(),||"drop table".to_string());
    // 使用函数
    schema.add_migration(add_field,remove_field);
    // 使用命令
    assert_eq!(vec!["create table","add field"],schema.execute());
    assert_eq!(vec!["remove field","drop table"],schema.rollback());
}
// 
type FnPtr=fn()->String;
// 定义命令
struct Command{
    execute:FnPtr,
    rollback:FnPtr,
}
// 存储迁移命令
struct Schema{
    commands:Vec<Command>,
}
impl Schema{
    fn new()->Self{
        Self { commands: vec![] }
    }
    fn add_migration(&mut self,execute:FnPtr,rollback:FnPtr){
        self.commands.push(Command{execute,rollback});
    }
    fn execute(&self)->Vec<String>{
        self.commands.iter().map(|cmd|(cmd.execute)()).collect()
    }
    fn rollback(&self)->Vec<String>{
        self.commands
        .iter()
        .rev()
        .map(|cmd|(cmd.rollback)())
        .collect()
    }
}

fn add_field()->String{
    "add field".to_string()
}
fn remove_field()->String{
    "remove field".to_string()
}

解释器模式

定义一种语言的文法,并提供解释器来解释句子

// 抽象表达式
trait Expression {
    fn interpret(&self, context: &mut Context) -> i32;
}
// 具体表达式
struct Number {
    value: i32,
}
impl Expression for Number {
    fn interpret(&self, _context: &mut Context) -> i32 {
        self.value
    }
}
// 具体表达式
struct AddExpression {
    left: Box<dyn Expression>,
    right: Box<dyn Expression>,
}
impl Expression for AddExpression {
    fn interpret(&self, context: &mut Context) -> i32 {
        self.left.interpret(context) + self.right.interpret(context)
    }
}
// 具体表达式
struct SubtractExpression {
    left: Box<dyn Expression>,
    right: Box<dyn Expression>,
}
impl Expression for SubtractExpression {
    fn interpret(&self, context: &mut Context) -> i32 {
        self.left.interpret(context) - self.right.interpret(context)
    }
}

struct Context {
    // 可以存储解释过程中的中间结果或其他上下文信息
}
fn main() {
    let mut context = Context {};
    let expression = AddExpression {
        left: Box::new(Number { value: 5 }),
        right: Box::new(SubtractExpression {
            left: Box::new(Number { value: 8 }),
            right: Box::new(Number { value: 3 }),
        }),
    };
    let result = expression.interpret(&mut context);
    println!("Result: {}", result);
}

中介模式

定义一个中介对象以封装一组对象之间的交互

use std::cell::RefCell;
use std::rc::Rc;

// 定义中介者接口
trait Mediator {
    fn notify(&self, sender: &str, event: &str);
}

// 定义组件结构
struct ComponentA {
    mediator: Rc<RefCell<dyn Mediator>>,
}
impl ComponentA {
    fn new(mediator: Rc<RefCell<dyn Mediator>>) -> Self {
        ComponentA { mediator }
    }

    fn do_something(&self) {
        println!("组件A做事");
        self.mediator.borrow().notify("ComponentA", "EventA");
    }
}

struct ComponentB {
    mediator: Rc<RefCell<dyn Mediator>>,
}
impl ComponentB {
    fn new(mediator: Rc<RefCell<dyn Mediator>>) -> Self {
        ComponentB { mediator }
    }

    fn do_something_else(&self) {
        println!("组件B做事");
        self.mediator.borrow().notify("ComponentB", "EventB");
    }
}

// 定义具体的中介者
struct ConcreteMediator {
    component_a: Option<Rc<ComponentA>>,
    component_b: Option<Rc<ComponentB>>,
}
impl ConcreteMediator {
    fn new() -> Self {
        ConcreteMediator {
            component_a: None,
            component_b: None,
        }
    }
    fn set_component_a(&mut self, component_a: Rc<ComponentA>) {
        self.component_a = Some(component_a);
    }
    fn set_component_b(&mut self, component_b: Rc<ComponentB>) {
        self.component_b = Some(component_b);
    }
}
// 实现中介者trait
impl Mediator for ConcreteMediator {
    fn notify(&self, sender: &str, event: &str) {
        match sender {
            "ComponentA" => {
                println!("中介者响应组件A事件: {}", event);
                if let Some(ref component_b) = self.component_b {
                    component_b.do_something_else();
                }
            }
            "ComponentB" => {
                println!("中介者响应组件B事件: {}", event);
                if let Some(ref component_a) = self.component_a {
                    component_a.do_something();
                }
            }
            _ => {}
        }
    }
}
fn main() {
    // 创建中介者,并将其包装为 `Rc<RefCell<ConcreteMediator>>`
    let mediator = Rc::new(RefCell::new(ConcreteMediator::new()));

    // 创建组件
    let component_a = Rc::new(ComponentA::new(Rc::clone(&mediator) as Rc<RefCell<dyn Mediator>>));
    let component_b = Rc::new(ComponentB::new(Rc::clone(&mediator) as Rc<RefCell<dyn Mediator>>));

    // 将组件注册到中介者中
    mediator.borrow_mut().set_component_a(Rc::clone(&component_a));
    mediator.borrow_mut().set_component_b(Rc::clone(&component_b));

    // 使用组件
    component_a.do_something();
    component_b.do_something_else();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2181182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【毕业/转行】想从事GIS开发工程师?如何规划?

既然是GIS开发&#xff0c;那就离不开学习编程 那如何学习才能掌握呢?如何才能达到企业的用人标准? 给大家梳理了学习的路线&#xff0c;想从事gis开发的小伙伴可以直接按这个路线学习! 共分为6大阶段&#xff0c;让你从纯小白到成熟的三维GIS开发工程师! 大纲&#xff1a…

Python:import语句的使用(详细解析)(一)

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 import语句是Python中一个很重要的机制&#xff0c;允许在一个文件中访问另一个文件的函数、类、变量等&#xff0c;本文就将进行详细介绍。 在具体谈论import语句前&a…

linux驱动编程——等待队列

一、等待队列 可实现调用read函数时阻塞等。 1、流程 &#xff08;1&#xff09;初始化等待队列头&#xff08;带参宏&#xff09; init_waitqueue_head(q) 等待队列头wq数据类型&#xff1a; wait_queue_head_t&#xff0c;等待条件condition&#xff1a;int型变量。 &…

Actor 并发控制模型

目录 一、模型概述 二、模型特点 三、模型组成 四、模型优势 五、应用实例 一般来说&#xff0c;我们有两种策略来在并发线程中实现通信&#xff1a;共享内存和消息传递。大多数传统语言&#xff0c;并发线程之间的通信使用的都是共享内存&#xff0c;共享内存最大的问题就…

分糖果C++

题目&#xff1a; 样例解释&#xff1a; 样例1解释 拿 k20 块糖放入篮子里。 篮子里现在糖果数 20≥n7&#xff0c;因此所有小朋友获得一块糖&#xff1b; 篮子里现在糖果数变成 13≥n7&#xff0c;因此所有小朋友获得一块糖&#xff1b; 篮子里现在糖果数变成 6<n7&#xf…

为本地生活赛道从业者赋能,易播易赚开启“抖音直播分享会”

9月22日&#xff0c;由杭州易播易赚科技有限公司主办的“抖音直播分享会”在杭州市富阳区召开&#xff0c;此次会议吸引了来自全国各地的抖音直播从业者、有志于加入抖音直播事业的创业者以及行业内知名专家齐聚一堂&#xff0c;共同探讨行业发展趋势、分享实战经验&#xff0c…

tomcat版本升级导致的umask问题

文章目录 1、问题背景2、问题分析3、深入研究4、umask4.1、umask的工作原理4.2、umask的计算方式4.3、示例4.4、如何设置umask4.5、注意事项 1、问题背景 我们的java服务是打成war包放在tomcat容器里运行的&#xff0c;有一天我像往常一样去查看服务的日志文件&#xff0c;却提…

Mysql高级篇(中)——多版本并发控制 MVCC

多版本并发控制 MVCC 一、概述二、基本原理三、实现原理四、示例解释五、MVCC 优点六、现实中的实现七、MVCC 三剑客1. ReadView2. Undo Log3. Purge4. 三者之间的关系&#xff1a;5. 示例6. 总结 八、MVCC 整体操作流程⭐、readview1. 作用2. 工作机制3. 数据版本的可见性判断…

[云服务器15] 全网最全!手把手搭建discourse论坛,100%完成

首先&#xff0c;由我隆重地介绍Discourse&#xff1a; 这是一个优秀的论坛部署平台&#xff0c;相较于flarum Discuz!&#xff0c;有着更加简洁的画面、完全开源等优点&#xff0c;同时资源占用也不高&#xff01; 并且&#xff0c;这和我们亲爱的雨云论坛是有几分相似的哦&…

国庆偷偷卷!小众降维!POD-Transformer多变量回归预测(Matlab)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现POD-Transformer多变量回归预测&#xff0c;本征正交分解数据降维融合Transformer多变量回归预测&#xff0c;使用SVD进行POD分解&#xff08;本征正交分解&#xff09;&#xff1b; 2.运行环境Matlab20…

Windows——解除Windows系统中文件名和目录路径的最大长度限制

第一步&#xff1a;打开本地组策略编辑器 按下Win R键打开运行窗口&#xff0c;输入 gpedit.msc 并回车&#xff0c;打开本地组策略编辑器。 第二步&#xff1a;开启 长路径设置 第三步&#xff1a;重启计算机

Windows环境Apache httpd 2.4 web服务器加载PHP8:Hello,world!

Windows环境Apache httpd 2.4 web服务器加载PHP8&#xff1a;Hello&#xff0c;world&#xff01; &#xff08;1&#xff09;首先需要安装apache httpd 2.4 web服务器&#xff1a; Windows安装启动apache httpd 2.4 web服务器-CSDN博客文章浏览阅读222次&#xff0c;点赞5次&…

Spark“数字人体”AI挑战赛_脊柱疾病智能诊断大赛_GPU赛道亚军比赛攻略_triple-Z团队

关联比赛: Spark“数字人体”AI挑战赛——脊柱疾病智能诊断大赛 triple-Z团队答题攻略 1 赛题分析 1.1 赛题回顾 本次比赛的任务是采用模型对核磁共振的脊柱图像进行智能检测。首先需要对5个椎体和6个椎间盘进行定位&#xff0c;这部分实际上就是11个关键点的检测任务&…

B2B商城交易解决方案:赋能企业有效重塑采购与销售新生态

在电商零售领域&#xff0c;商城系统始终是企业搭建商城的关键利器。 伴随着电商行业的蓬勃发展&#xff0c;各类新模式层出不穷&#xff0c;各种商城系统也应运而生&#xff0c;其中B2B商城更是最为常见的一种。 近年来&#xff0c;得益于电子商务的迅猛发展&#xff0c;B2B商…

C++入门基础知识92(实例)——实例17【实现一个简单的计算器】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于实现一个简单的计算器的相关内容&#x…

详细整理!!html5常用标签

文章目录 前言一、HTML简介1.HTML文件结构2.各标签意义 二、HTML标签介绍1.标题标签2.段落标签3. 换行标签4.hr标签5. span标签6.div标签7.img标签8.超链接标签9.注释标签10.空格11.格式化标签12.sup上标和sub下标13. pre预格式化标签14.table 表格标签table 标签基础内容合并单…

Java中异常的认识和创建

文章目录 前言一、异常的概念与体系结构 1.1 异常的概念1.2 异常的体系结构1.3 异常的分类二、异常的处理 2.1.防御式编程2.2 异常的抛出2.3 异常的捕获2.4 异常的处理流程三、自定义异常类 一、异常的概念与体系结构 1.1 异常的概念 在生活中&#xff0c;一个人表情痛苦&…

TI DSP TMS320F280025 Note16:EPWM的原理与使用

TMS320F280025 模数转换器(ADC) ` 文章目录 TMS320F280025 模数转换器(ADC)时基TB子模块计数比较CC子模块动作AQ子模块死区DB子模块斩波PC子模块错误联防模块TZ子模块数字比较DC子模块中断ET子模块EPWM的使用EPWMDriver.cEPWMDriver.h每个EPWM模块都包含多个子模块:时基TB子模…

系列二、案例实操

一、创建表空间 1.1、概述 在Oracle数据库中&#xff0c;表空间是一个逻辑存储单位&#xff0c;它是Oracle数据库中存储数据的地方。 1.2、超级管理员登录 sqlplus / as sysdba 1.3、创建表空间 create tablespace water_boss datafile C:\Programs\oracle11g\oradata\orcl\…

【NTN 卫星通信】基于NR的NTN RAN架构

1 引言 3GPP中,38.821协议中,研究了如何最大限度地减少对NG-RAN中新接口和协议的需求,以支持非地面网络。 研究了包括透传星和再生星的RAN架构。 2 基于透传星的NG-RAN架构 2.1 概述: 对于透传模式,卫星有效载荷在上行链路和下行链路方向上实现频率转换和射频放大器。它…