为这个令人费解的标题道歉!
我是生锈新手,我正试图解决一个非常具体的问题。到目前为止,我尝试过的解决方案似乎都没有在语言范围内很好地工作。
我有一个包含数据的结构(称为Model),它还包含一个用于“策略”结构的动态框。有几个不同的策略结构,它们是由一个共同的特性(策略)识别的,每个特征都包含通过他们的“执行策略”方法来修改模型的单独方法。通过这样做,I可以通过像状态机一样更改模型的策略实例来动态地更改使用的策略。
每种策略都是不可变的,但它们会改变模型的数据。它们有时确实包含它们自己的不可变数据,因此枚举似乎是一种尴尬的适合。
trait Strategy {
fn execute_strategy(&self, model: &mut Model);
}
struct Strategy1;
impl Strategy for Strategy1 {
fn execute_strategy(&self, model: &mut Model) {
...
}
}
struct Strategy2;
impl Strategy for Strategy2 {
fn execute_strategy(&self, model: &mut Model) {
...
}
}
struct Model {
strategy: Box<dyn Strategy>,
}现在我遇到问题的地方是执行这个策略。
impl Model {
fn run(&mut self) {
(*self.strategy).execute_strategy(self); // WONT COMPILE
}
}我明白为什么上面的内容不能编译--它看到了自我被不断地、不断地借用。这有什么惯用的解决办法吗?每种策略都在真空中工作,只对模型进行修改。这些策略本身是不变的,因此,上述措施似乎是安全的。
新年快乐,提前感谢您的帮助!
发布于 2022-01-01 07:08:35
我不知道解决这个问题最惯用的方法是什么,但我能想到一些。一种方法是从strategy中删除self,这样在操作期间它就不是self的成员,然后再放回去。这似乎是一种反模式,因为您可以忘记事后将其放回(特别是当您忘记处理错误时):
impl Model {
fn run(&mut self) {
let strategy = std::mem::replace(&mut self.strategy, Box::new(EmptyStrategy {}));
strategy.execute_strategy(self);
let _ = std::mem::replace(&mut self.strategy, strategy);
}
}注意,如果使用Option<Box<dyn Strategy>>,有一个更好的API :您可以用self.strategy.take()获取(并擦除)成员,并用self.strategy.replace() (或赋值)替换成员。但这并不能解决安全问题。
如果您的结构只有1-2个成员,一个更好的方法是对这些成员进行操作,而不是对结构本身进行操作。您可以按以下方式对结构进行分解并运行策略:
impl Model {
fn run(&mut self) {
let Model {
data,
data2,
strategy,
} = self;
strategy.execute_strategy(data, data2);
}
}最通用和最安全的解决方案可能是将策略存储在Rc或Arc中,然后为执行策略创建一个新的引用副本:
struct Model {
strategy: Arc<Box<dyn Strategy>>,
}
impl Model {
fn run(&mut self) {
self.strategy.clone().execute_strategy(self);
}
}https://stackoverflow.com/questions/70546609
复制相似问题