策略模式属于对象的行为模式,其用意是针对一组算法,将每一个算法封装到具有公共接口的独立的类中,从而在不影响客户端的情况下可以切换相应的算法。
未使用策略模式案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class TravelStrategy { enum Strategy{ WALK,PLANE,SUBWAY } private Strategy strategy; public TravelStrategy(Strategy strategy){ this.strategy=strategy; } public void travel(){ if(strategy==Strategy.WALK){ print("walk"); }else if(strategy==Strategy.PLANE){ print("plane"); }else if(strategy==Strategy.SUBWAY){ print("subway"); } } public void print(String str){ System.out.println("出行旅游的方式为:"+str); } public static void main(String[] args) { TravelStrategy walk=new TravelStrategy(Strategy.WALK); walk.travel(); TravelStrategy plane=new TravelStrategy(Strategy.PLANE); plane.travel(); TravelStrategy subway=new TravelStrategy(Strategy.SUBWAY); subway.travel(); } }
|
通过switch或者if语句,来判断选择哪一种策略算法,一旦策略增加或者减少修改,就不得不增加新的语句,这就违背了面向对象的原则之一,对修改封闭。
使用策略模式案例
定义策略接口(抽象策略)
1 2 3
| public interface Strategy { void travel(); }
|
将不同的算法封装到实现该策略接口的具体的类中(具体策略)
1 2 3 4 5 6 7 8
| public class WalkStrategy implements Strategy{
@Override public void travel() { System.out.println("walk"); }
}
|
1 2 3 4 5 6 7 8
| public class PlaneStrategy implements Strategy{
@Override public void travel() { System.out.println("plane"); }
}
|
1 2 3 4 5 6 7 8
| public class SubwayStrategy implements Strategy{
@Override public void travel() { System.out.println("subway"); }
}
|
策略环境(持有抽象策略引用的环境类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class TravelContext { Strategy strategy;
public Strategy getStrategy() { return strategy; }
public void setStrategy(Strategy strategy) { this.strategy = strategy; }
public void travel() { if (strategy != null) { strategy.travel(); } } }
|
具体使用
1 2 3 4 5 6 7 8 9 10 11
| public class Main { public static void main(String[] args) { TravelContext travelContext=new TravelContext(); travelContext.setStrategy(new PlaneStrategy()); travelContext.travel(); travelContext.setStrategy(new WalkStrategy()); travelContext.travel(); travelContext.setStrategy(new SubwayStrategy()); travelContext.travel(); } }
|
若想增加新的策略(添加新的策略实现类即可)
1 2 3 4 5 6 7 8
| public class BikeStrategy implements Strategy{
@Override public void travel() { System.out.println("bike"); }
}
|
1 2 3
| TravelContext travelContext=new TravelContext(); travelContext.setStrategy(new BikeStrategy()); travelContext.travel();
|
总结
面向对象的对修改封闭,对扩展开放。
Android源码中的使用
策略接口
1 2 3 4 5
| public interface TypeEvaluator<T> {
public T evaluate(float fraction, T startValue, T endValue);
}
|
多个策略实现例如
1 2 3 4 5 6 7
| public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(startInt + fraction * (endValue - startInt)); } }
|
1 2 3 4 5 6 7
| public class FloatEvaluator implements TypeEvaluator<Number> {
public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat); } }
|
其他略…
其他使用场景举例
例如:一个电商类平台等购物车系统,除了把货品的单价乘以数量之外,可能会有一些优惠活动。比如说,对高级会员提供5折优惠,对中级会员提供7折优惠,对初级会员提供9折优惠
那么这就涉及到了三种算法
首先定义折扣抽样策略接口
1 2 3 4 5 6 7 8
| public interface MemberStrategy {
public double calcPrice(double booksPrice); }
|
初级会员折扣策略
1 2 3 4 5 6 7 8 9 10
| public class PrimaryMemberStrategy implements MemberStrategy {
@Override public double calcPrice(double booksPrice) { System.out.println("对于初级会员的9折折扣"); return booksPrice*0.9; }
}
|
1 2 3 4 5 6 7 8 9
| public class AdvancedMemberStrategy implements MemberStrategy {
@Override public double calcPrice(double booksPrice) { System.out.println("对于高级会员的折扣为5折"); return booksPrice * 0.5; } }
|
1 2 3 4 5 6 7 8 9 10
| public class IntermediateMemberStrategy implements MemberStrategy {
@Override public double calcPrice(double booksPrice) {
System.out.println("对于中级会员的折扣为7折"); return booksPrice * 0.7; }
}
|
策略环境类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class Price { private MemberStrategy strategy;
public Price(MemberStrategy strategy){ this.strategy = strategy; }
public double quote(double booksPrice){ return this.strategy.calcPrice(booksPrice); } }
|
客户端的使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Client {
public static void main(String[] args) { MemberStrategy strategy = new AdvancedMemberStrategy(); Price price = new Price(strategy); double quote = price.quote(300); System.out.println("图书的最终价格为:" + quote); }
}
|
可以看出
- 策略模式的重心不是提供算法,而是对多种算法的封装
- 各个算法相对独立平等
- 算法可以相互切换,但在同一时刻只能使用一种策略
- 面向对象的:对修改封闭,对拓展开放
- 避免使用switch和if多重条件语句,方便维护
- 缺点:客户端事先知道有多少种策略,并且每个策略的区别