一个送信的逻辑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#[derive(Clone)]
pub struct Letter {
    text: String,
}

pub struct Envelope {
    letter: Option<Letter>,
}

pub struct PickupLorryHandle {
    done: bool,
}

impl Letter {
    pub fn new(text: String) -> Self {
        Letter { text: text }
    }
}

impl Envelope {
    pub fn wrap(&mut self, letter: &Letter) {
        self.letter = Some(letter.clone());
    }
}

pub fn buy_prestamped_envelope() -> Envelope {
    Envelope { letter: None }
}

impl PickupLorryHandle {
    pub fn pickup(&mut self, _envelope: &Envelope) {
        // give letter
    }

    pub fn done(&mut self) {
        self.done = true;
        println!("sent");
    }
}

pub fn order_pickup() -> PickupLorryHandle {
    PickupLorryHandle { done: false }
}

fn main() {
    let letter = Letter::new(String::from("Dear RustFest"));
    let mut envelope = buy_prestamped_envelope();
    envelope.wrap(&letter);
    let mut lorry = order_pickup();
    lorry.pickup(&envelope);
    lorry.done();
}

上面存在的问题:

  1. Letter 可能被复制多份,装在不同的 envelope 中, 不安全。
  2. 信封中可能有信,可能没信;或者同一个信封可能装不同的信件,不安全。
  3. 无法保证信一定交给了邮车。

下面使用 RAII 重构上面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
pub struct Letter {
    text: String,
}

// 空信封
pub struct EmptyEnvelope {}

// 关闭了的信封
pub struct ClosedEnvelope { letter: Letter }

pub struct PickupLorryHandle {}

impl Letter {
    pub fn new(text: String) -> Self {
        Letter { text: text }
    }
}

impl EmptyEnvelope {
    pub fn wrap(self, letter: Letter) -> ClosedEnvelope {
        ClosedEnvelope { letter: letter }
    }
}


pub fn buy_prestamped_envelope() -> EmptyEnvelope {
    EmptyEnvelope { }
}

impl PickupLorryHandle {
    pub fn pickup(&mut self, _envelope: ClosedEnvelope) {
        // give letter
    }

}

// 实现析构函数
impl Drop for PickupLorryHandle {
    fn drop(&mut self) {
        println!("sent");
    }
}

pub fn order_pickup() -> PickupLorryHandle {
    PickupLorryHandle {}
}

fn main() {
    let letter = Letter::new(String::from("Dear RustFest"));
    let envelope = buy_prestamped_envelope();
    let closed_envelope = envelope.wrap(letter);
    let mut lorry = order_pickup();
    lorry.pickup(closed_envelope);
}