初始化需要相互通信的对象网络的技术是什么?

时间:2020-08-02 20:26:40

标签: rust

我有一堆实现某些特征的对象。对于每个对象,我需要注入一个特征向量,即监听器。

我遇到的问题是,我需要在初始化期间对对象进行引用计数和可变。这是构造:

impl Game {
    fn new() -> Self {
        let bg = Rc::new(Background::new());
        let time_counter = Rc::new(TimeCounter::new());
        let flag_counter = Rc::new(FlagCounter::new());
        let game_state_button = Rc::new(GameStateButton::new());
        let grid = Rc::new(Grid::new());

        let object_listeners: Vec<Weak<dyn ObjectListener>> = vec![
            Rc::downgrade(&game_state_button) as Weak<dyn ObjectListener>,
            Rc::downgrade(&flag_counter) as Weak<dyn ObjectListener>,
        ];
        grid.assign_object_listeners(object_listeners);

        let game_state_listeners: Vec<Weak<dyn GameStateListener>> = vec![
            Rc::downgrade(&time_counter) as Weak<dyn GameStateListener>,
            Rc::downgrade(&flag_counter) as Weak<dyn GameStateListener>,
            Rc::downgrade(&grid) as Weak<dyn GameStateListener>,
        ];
        game_state_button.assign_game_state_listeners(game_state_listeners);

        let flag_state_listeners: Vec<Weak<dyn FlagStateListener>> = vec![
            Rc::downgrade(&grid) as Weak<dyn FlagStateListener>,
        ];
        flag_counter.assign_flag_state_listeners(flag_state_listeners);

        let sprites: Vec<Rc<dyn Sprite>> = vec![
            Rc::clone(&bg) as Rc<dyn Sprite>,
            Rc::clone(&time_counter) as Rc<dyn Sprite>,
            Rc::clone(&flag_counter) as Rc<dyn Sprite>,
            Rc::clone(&game_state_button) as Rc<dyn Sprite>,
            Rc::clone(&grid) as Rc<dyn Sprite>,
        ];
        Game { sprites }
    }
}

分配将使对象变异,从而导致Rc出现问题。我可以使用RefCell,它虽然有效,但感觉不对。我看过channel,我可以创建一堆通道,然后在对象构造期间将它们注入(发送或接收),但这也感觉不对。我看过specs并仍在消化它。

有人能建议一个更好的组织来编码对象之间的通信图吗?作为最后的选择,我可以将侦听器塞入Game对象中,然后将引用计数的游戏对象注入每个对象中,但是感觉很扭曲。

这是我解决许多问题的方法。我意识到我有一个通讯图,供对象使用。我构造了一个帮助程序,以简化通道与对象的连接。然后,我构造图,并在构造过程中将其注入对象中。这也清除了所有权,因为不再需要Rc。现在是下面的代码:

pub fn new(layout: Layout) -> Game {
    // get all the channel wiring setup
    let mut channels = ChannelWiring::default();
    channels.wire::<Grid, Button>();
    channels.wire::<Grid, FlagCounter>();

    channels.wire::<Button, TimeCounter>();
    channels.wire::<Button, FlagCounter>();
    channels.wire::<Button, Grid>();

    channels.wire::<FlagCounter, Grid>();

    let mut sprites: Vec<Box<dyn Sprite>> = Vec::new();

    // create the underlying objects, and own via trait
    sprites.push(Box::new(Background {}));
    sprites.push(Box::new(TimeCounter::new(&mut channels)));
    sprites.push(Box::new(FlagCounter::new(layout, &mut channels)));
    sprites.push(Box::new(Button::new(layout, &mut channels)));
    sprites.push(Box::new(Grid::new(layout, &mut channels)));

    // finally create the game object
    Game { sprites: sprites }
}

随着引用计数的消失,对RefCell的需求也消失了。

0 个答案:

没有答案
相关问题