Rust中的设计模式:构建者模式(Builder)

614次阅读  |  发布于1年以前

构建者模式介绍

构建器模式是一种创建设计模式,也就是说,它是一种用于创建或实例化类对象的模式。它用于将构建过程分解为更小、更易于管理和可测试的步骤。

在Rust中,我们可以使用结构体和特征来实现这个模式。

如图:

1,Director:这是构建器的客户端,它请求构建一些产品。

2,Builder:这是任何生成器的通用接口,它包含构建Product的方法。

3,ConcreteBuilder:这是构建Product的具体类。因为我们只能使用一个接口,所以可以交换不同的ConcreteBuilders实例来构建不同的产品。

4,我们要构建的产品是Product,这也可以定义一个接口。

在Rust中实现构建者模式

新建一个Rust项目:

cargo new rust_builder

Bicycle结构体

#[derive(Clone,Debug)]
pub struct Bicycle {
    number_of_wheels: i8,
    bike_type: String
}

impl Bicycle {
    fn new()->Self {
        Bicycle { number_of_wheels: 0, bike_type: "".to_string() }
     }
}

1,Bicycle结构体只有两个字段:number_of_wheels和bike_type。

2,我们用空值为Bicycle定义了一个构造函数。

3,Bicycle结构体有两个特征:- Clone,因此我们可以从构建器返回一个克隆;

BicycleBuilder特征

pub trait BicycleBuilder {
    fn add_wheels(&mut self)->&mut dyn BicycleBuilder;
    fn set_type(&mut self)->&mut dyn BicycleBuilder;
    fn build(&self) -> Bicycle;
}

1,trait有三个方法:add_wheels用来设置轮子的数量,set_type用来设置自行车类型,还有一个build方法用来返回Bicyle。

2,add_wheels和set_type接受一个可变的self作为参数,因为它们改变了bicycle字段。

3,因为build只返回一个克隆,不需要也不希望有可变性。

4,add_wheels和set_type方法返回指向dyn BicycleBuilder的指针。这是因为BicycleBuilder是一个特征,我们需要动态调度。

构建器模式的实现

struct ATBBuilder {
    bicycle: Bicycle
}

impl BicycleBuilder for ATBBuilder {
    fn add_wheels(&mut self) -> &mut dyn BicycleBuilder {
        self.bicycle.number_of_wheels=2;
        self
    }

    fn set_type(&mut self) -> &mut dyn BicycleBuilder {
        self.bicycle.bike_type="ATB".to_string();
        self
    }

    fn build(&self)->Bicycle {
        self.bicycle.clone()
    }
}

1,ATBBuilder包含要生产的产品,即自行车。

2,实现非常简单,所有的方法都返回self,所以它们可以被链式调用。

3,build方法返回一个克隆。

为了更好地衡量,我们还可以引入一个StreetBikeBuilder:

struct StreetBikeBuilder {
    bicycle:Bicycle
}

impl BicycleBuilder for StreetBikeBuilder {
    fn add_wheels(&mut self) -> &mut dyn BicycleBuilder {
        self.bicycle.number_of_wheels=3;
        self
    }

    fn set_type(&mut self) -> &mut dyn BicycleBuilder {
        self.bicycle.bike_type="Street".to_string();
        self
    }

    fn build(&self)->Bicycle {
        self.bicycle.clone()
    }
}

使用BikeEngineer组合

struct BikeEngineer {
    builder: Box<dyn BicycleBuilder>
}

impl BikeEngineer {
    fn new(builder: Box<dyn BicycleBuilder>)->Self {
        BikeEngineer { builder: builder }
    }
    fn construct_bike(&mut self)->Bicycle {
        self.builder
        .add_wheels()
        .set_type()
        .build()
    }
}

1,我们有Box作为构建器的类型。这是因为我们需要a.动态调度和b.我们在编译时不知道BicycleBuilder类的大小,这就是为什么我们需要一个box。

2,我们定义了一个接受这样一个box的构造函数,并将其分配给生成器字段。还要注意,我们返回Self。

3,construct_bike方法只是添加轮子,设置类型并返回成品。

测试

fn main() {
    let builder=Box::new(StreetBikeBuilder{bicycle:Bicycle::new()});
    let mut engineer=BikeEngineer::new(builder);

    let bike=engineer.construct_bike();
    println!("{:?}",bike);
}

执行cargo run,结果如下:

Bicycle { number_of_wheels: 3, bike_type: "Street" }

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8