Rust中的设计模式:策略模式(Strategy)

392次阅读  |  发布于4月以前

策略模式介绍

策略模式是一种行为设计模式,允许你定义一系列算法,将它们封装为一个对象,并借助特征使它们可互换。

  1. 上下文想要应用某种算法,为此它包含了一个实现algorithm方法的Strategy特征。
  2. 当需要该策略时,将启动StrategyA或StrategyB,并调用算法方法。

有人认为这是依赖注入的一种形式,因为方法只在接口上调用,而不是在具体对象上调用。

在Rust中实现策略模式

新建一个Rust项目:

cargo new strategy_pattern

我们将从定义TravelStrategy开始

trait TravelStrategy {
    fn travel(&self, distance: i16);    
}

然后我们将定义TrainStrategy:

struct TrainStrategy;

impl TravelStrategy for TrainStrategy {
    fn travel(&self, distance: i16) {
        println!("Travelled {} km by train", distance);
    }
}

TrainStrategy结构体为空。我们在上面实现了一个travel方法,它只是打印旅行的距离。

CarStrategy也类似:

struct CarStrategy;

impl TravelStrategy for CarStrategy {
    fn travel(&self, distance: i16) {
        println!("Travelled {} km by car", distance);
    }
}

定义TravelHub

struct TravelHub<T: TravelStrategy> {
    strategy: T,
}

我们在这里使用泛型,T: TravelStrategy意味着我们可以拥有任何类型,只要它实现了TravelStrategy特征。

为什么是泛型?泛型使得在具体类中传递更容易,而无需求助于Box或类似的方法,并且它使代码更具可读性。

现在实现TravelHub:

impl<T: TravelStrategy> TravelHub<T> {
    fn new(strategy: T)->Self {
        Self {
            strategy
        }
    }

    fn customer_travel(&self, distance:i16) {
        self.strategy.travel(distance);
    }
}

1,首先定义一个构造函数,它获取一个具体类作为形参。这个具体的类必须实现TravelStrategy特性。

2,然后我们定义customer_travel方法,它只调用所选策略上的travel方法。

测试

fn main() {
    let travelhub = TravelHub::new(TrainStrategy{});
    travelhub.customer_travel(20);
}

用TrainStrategy作为参数实例化一个travelhub。由于TrainStrategy实现了TravelStrategy特性,我们可以将其作为参数传递。

执行cargo run,结果如下:

Travelled 20 km by train

总结

如你所见,实现非常简单。泛型的使用可以避免使用Box类型,它使代码更具可读性。这种模式也可以说是依赖注入的一种形式,因为在调用方不知道底层类的情况下,只调用接口上的方法。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8