代理模式介绍
我们在这里看到了什么?
1,一个Drivable接口,在Rust中就是trait,这个trait只有一个方法:drive(int distance)。
2,两个结构体:Car和Bicycle,它们都实现了Drivable特性。
3,一个具体的VehicleProxy结构体,它实现了Drivable特征,但它也包含了一个实现Drivable特征的具体对象。
4,一个具体的VehicleManager结构体,它保存了VehicleProxy的实例,它不知道将要驱动的车辆的确切类型,也不知道任何实现细节。
代理模式在某些情况下非常有用:
1,如果你想控制/监控对具体结构体的访问。
如何在Rust中实现代理模式?
cargo new proxy_pattern
我们将一步一步地进行实施。首先打开main.rs,
pub trait Drivable {
fn drive(&self, distance:u32);
}
&self - 指向实现特征的结构体
distance - 距离
pub struct Car {}
impl Drivable for Car {
fn drive(&self, distance: u32) {
println!("I drove {} kilometres in my car", distance);
}
}
1,我们定义一个Car结构体,由于此结构体没有其他属性,因此该结构体为空。
2,我们在Car结构体上实现了Drivable特征的方法drive,该方法只打印一条消息。
pub struct Bicycle {}
impl Drivable for Bicycle {
fn drive(&self, distance: u32) {
println!("I drove {} kilometres on my bicycle", distance);
}
}
pub struct VehicleProxy {
pub real_subject: Box<dyn Drivable+'static>
}
impl Drivable for VehicleProxy {
fn drive(&self, distance: u32) {
self.real_subject.drive(distance);
}
}
1,real_subject字段是一个Box,因为在编译时还不知道大小。
dyn Drivable:因为Drivable是一个trait,对它的方法调用将被动态分派。
然后我们看到一个'static的生命周期,这意味着该字段在程序的整个运行过程中都存在。
3,在实现部分,我们看到在real_subject上调用了drive方法。
pub struct VehicleManager {
pub vehicle_proxy: Box<VehicleProxy>
}
impl Drivable for VehicleManager {
fn drive(&self, distance: u32) {
self.vehicle_proxy.drive(distance);
}
}
1,因为我们不知道VehicleProxy将引用哪个类,所以在编译时大小是未知的,所以我们再次使用Box。
2,注意,在vehicle_proxy字段上调用drive方法。
fn main() {
let my_vehicle = Box::new(Bicycle {});
let my_proxy = Box::new(VehicleProxy {
real_subject: my_vehicle,
});
let my_vehicle_manager = Box::new(VehicleManager {
vehicle_proxy: my_proxy,
});
my_vehicle_manager.drive(20);
}
I drove 20 kilometres on my bicycle