一、介绍,定义
策略模式定义了一系列的算法,并将每一个封装起来,而且使它们可以相互替换。策略模式让算法模式独立于使用它的客户而独立变化。
二、使用场景
针对同一类型的问题的多种处理方式,仅仅是具体行为有差别时。
需要安全地的封装多种同一类型的操作时。
出现同一抽象类有多个子类,而又需要if-else或者switch-case来选择具体子类时。
三、UML类图
![](https://img.haomeiwen.com/i14355128/47e628d45c45be86.png)
Context :用来操作策略的上下文环境;
Stragety:策略的抽象;
StagetyA、StagetyB:具体的策略的实现
四、简单实现
根据公里数,计算公交车和地铁的票价
最初版本:
public class PriceCalculator{
//公交车
private static final int BUS = 1;
//地铁
private static final int SUBWAY = 2;
public static void main(String [] args){
PriceCalculator ca = new PriceCalcluator();
System.out.println("16公里公交票价:"+ca.calculatePrice(16,SUBWAY ));
System.out.println("16公里地铁票价:"+ca.calculatePrice(16,BUS));
}
//十公里内1元,超过十公里后,每加一元可乘5公里
private int busPrice(int km){
int extraTotal = km-10;
int extraFactor = extraTotal/5;
int fraction = extraTotal %5'
int price = 1+extraFactor*1;
return fraction >0?++price:price;
}
//6公里内3元,6-12公里4元,12-22公里5元,22-32公里6元
private int subwayPrice(int km){
if(km<6){
return 3;
}else if(km>6&&km<12){
return 4;
}else if(km>12&&km<22){
return 5;
}else if(km>22&&km<32){
return 6;
}
return 7;//其他简化为7
}
int calculatePrice(int km,int type){
if(type == BUS){
return busPrice(km);
}else if(type == SUBWAY){
return subwayPrice(km);
}
return 0;
}
}
每增加一种出行方式,就要在PriceCalculator中添加一个方法计算出租车出行的价格,并在calculatePrice中添加一个判断,各种if-else缠绕其中。下面用策略模式重构:
定义一个抽象的价格计算接口:
public interface CalculatorStrategy{
int calculatePrice(int km);
}
每种方式都实现了此接口:
public class BusStrategy implements CalculatorStrategy{
@Override
public int calculatePrice(int km){
int extraTotal = km-10;
int extraFactor = extraTotal/5;
int fraction = extraTotal %5'
int price = 1+extraFactor*1;
return fraction >0?++price:price;
}
}
public class SubwayStrategy implements CalculatorStrategy{
@Override
public int calculatePrice(int km){
if(km<6){
return 3;
}else if(km>6&&km<12){
return 4;
}else if(km>12&&km<22){
return 5;
}else if(km>22&&km<32){
return 6;
}
return 7;//其他简化为7
}
}
再创建一个扮演Context角色的类
public class TranficCalculator{
public static void main(String[]args){
TranficCalculator ca = new TranficCalculator();
//设置计算策略
ca.setStrategy(new BusStrategy);
//计算价格
System.out.println("16公里公交票价:"+ca.calculatePrice(16));
}
CalculatorStrategy mStrategy;
public void setStrategy(CalculatorStrategy mStrategy){
this.mStrategy = mStrategy;
}
public int calculatePrice(int km){
return mStrategy.calculatePrice(km);
}
}
这样当我们有新的方式时,只要添加一个计算类后设置给TranficCalculator 即可。
五、模式的优缺点:
策略模式主要用来分离算法,根据相同的行为抽象来做不同的具体策略实现。很好的实现了开闭原则,也就是定义抽象,注入具体实现,从而达到很好的可扩展性。
优点
使用了组合,使架构更加灵活
富有弹性,可以较好的应对变化(开闭原则)
更好的代码复用性(相对于继承)
消除大量的条件语句
缺点
随着策略的增加,子类也会变得繁多。
选择何种算法需要客户端来创建对象,增加了耦合,这里可以通过与工厂模式结合解决该问题
网友评论