我有一堆实现某些特征的对象。对于每个对象,我需要注入一个特征向量,即监听器。
我遇到的问题是,我需要在初始化期间对对象进行引用计数和可变。这是构造:
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的需求也消失了。