策略模式(Strategy Pattern)
概念
策略模式 定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
策略模式把 对象本身和运算规则 区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。
组成
策略模式 UML 图如下所示:
(图片来自维基百科)
策略模式将不同的算法封装成类,如上图的 ConcreteStategyA、ConcreteStrategyB,而不同的策略都实现于接口 Strategy,然后在 Context 中聚合 Strategy interface, 当需要改变 策略 时,仅仅需要改动 Context 的 Strategy interface,大大提高了灵活性。
环境类(Context):用一个 ConcreteStrategy 对象来配置。维护一个对 Strategy 对象的引用。可定义一个接口来让 Strategy 访问它的数据。
抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context 使用这个接口来调用某 ConcreteStrategy 定义的算法。
具体策略类(ConcreteStrategy):以 Strategy 接口实现某具体算法。
例子
出行旅游:可以选择不同的交通方式
接口类:TravelStategy
package DesignPattern.Strategy;
public interface TravelStrategy {
public void travel();
}
飞机出行类:AirplainTravelStrategy
package DesignPattern.Strategy;
public class AirplainTravelStrategy implements TravelStrategy {
public void travel() {
System.out.println("Airplain Travel");
}
}
火车出行类:TrainTravelStategy
package DesignPattern.Strategy;
public class TrainTravelStrategy implements TravelStrategy {
public void travel() {
System.out.println("Train Travel");
}
}
实现类
package DesignPattern.Strategy;
public class People {
public People(){ }
//改变不同的策略
public void setStrategy(TravelStrategy strategy) {
this.strategy = strategy;
}
//实施当前策略
public void travel() {
strategy.travel();
}
private TravelStrategy strategy;
public static void main(String[] args) {
People people = new People();
people.setStrategy(new AirplainTravelStrategy());
people.travel();
people.setStrategy(new TrainTravelStrategy());
people.travel();
}
}
运行结果:
适用场景
- 多个类但区别仅是行为表现,可以使用 Strategy 模式,且在执行过程中动态 更换行为。
- 需要使用不同策略,且将来可能增加策略。
- 提供给客户使用不同的策略,但避免暴露算法的细节。
优缺点
优点
- 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
- 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
- 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
- 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。
完
参考:
策略模式 —— wiki 百科
策略模式 —— 百度百科
设计模式 ( 十八 ) 策略模式Strategy(对象行为型)