• 设计模式中的构建者模式
  • 发布于 2个月前
  • 198 热度
    0 评论
构建者模式介绍
构建器模式是一种创建设计模式,也就是说,它是一种用于创建或实例化类对象的模式。它用于将构建过程分解为更小、更易于管理和可测试的步骤。在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,因此我们可以从构建器返回一个克隆;

Debug,因此我们可以打印出一个用户友好的字符串。因为i8和String都支持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
    }
    // 堆代码 duidaima.com
    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<dyn BicycleBuilder>作为构建器的类型。这是因为我们需要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" }

用户评论