首页 > 编程笔记 > Java笔记 阅读:10

策略模式(Java实现)

策略模式有时又称为政策模式(policy pattern),因为它会精确描述对象在某种情况或状态下,应该采用什么样的步骤执行操作。

策略模式由一系列算法构成,这些算法都经过了适当的封装。该模式使得某个对象能够选用不同的算法回应用户的需求。这样设计令这些算法能够各自进化,而且不会影响到客户代码。另外,这也使得用户能够当场指定最适合目前状况的一种算法。

换句话说,策略模式让用户能够在表示各种算法的策略对象里选择一个,并将其挂接在目标对象上,从而令该对象能够采用这种算法或策略来执行某个操作。

策略模式在JDK中的运用

与中介者模式类似,这个模式也经常被用到,但是不容易被立刻想起来。

Java 集合框架位于 java.base 模块的 java.util 包中,这个包里有个名为 Comparator 的接口,用来表示我们在判定对象之间的大小关系时所使用的策略。我们在给某一系列元素排序的时候经常会用到这个接口,例如,可以把实现了该接口的某个类的实例当成参数传给 Collections.sort() 方法,让它采用这个实例所描述的策略给元素排序。

还有一个出现策略模式的地方,比 Comparator 用途更广,这就是 Stream API 里的 map() 或 filter() 方法,这些方法接受一个实现了某种函数接口的类的实例作为参数,并采用该实例所描述的策略来执行映射或过滤操作。它们与 Comparator 一样,都位于 java.base 模块中,但是属于 java.util.stream 包。

策略模式实例演示

假设某位司机拥有驾驶各种车辆的多个驾照。每种车辆的驾驶策略都稍有区别:
public static void main(String[] args) {
    System.out.println("Strategy Pattern, changing transport options");
    var driver = new VehicleDriver(new CarStrategy());
    driver.transport();
    driver.changeStrategy(new BusStrategy());
    driver.transport();
    driver.changeStrategy(new TruckStrategy());
    driver.transport();
}
程序输出结果如下:

Strategy Pattern, changing transport options
Car, four persons transport
Bus, whole crew transport
Truck, transporting heavy load

VehicleDriver 实例只需通过 TransportStrategy 类型的 strategy 字段持有指向当前策略对象的引用即可,而无须同时管理各种具体的驾驶策略。

【实例】VehicleDriver 实例通过策略对象所定义的通用方法来执行操作,而不用关注具体的策略。
class VehicleDriver {
    private TransportStrategy strategy;
    VehicleDriver(TransportStrategy strategy) {
        this.strategy = strategy;
    }
    void changeStrategy(TransportStrategy strategy){
        this.strategy = strategy;
    }
    void transport(){
        strategy.transport();
    }
}
用户可以在程序运行期间选择使用其中一种驾驶策略。这些策略都经过了适当的封装:


图 1 用UML类图演示如何轻松地定义一种新的策略

这个简单的例子很好地演示了如何用一种隔离程度相当高的办法来实现策略模式。

在本例中,司机可以根据自己要开的车辆是何种类型来选择与之相应的驾驶策略。每一种驾驶策略的代码都自成一体,而且这些策略的代码与程序的其他代码之间也互不干扰。

这种做法很适合用来给复杂的算法或操作执行封装,使得用户只需使用封装好的策略即可,而无须了解这些策略的细节。

相关文章