策略模式定义了一系列算法,并将每个算法封装起来,并且他们还能够相互替换。策略模式让算法独立于使用它的客户而独立变化。算法
Context 环境类设计模式
环境类是使用算法的角色,它在实现某个方法时能够采起多种策略。在环境类中维护着对抽象策略类的引用。安全
Strategy 抽象策略类bash
为所支持的算法声明抽象方法ide
ConcreteStrategy具体策略类工具
具体实现了抽象策略类中定义的算法测试
以坐车出行为例子,来简单说明,假设选择的交通工具均以路程来计价,咱们须要计算最终需支付的金额。 小A要出去玩耍,走好出门,来了辆公交车,小A果断上去坐上了。优化
public class PriceCalculator {
public static void main(String[] args) {
PriceCalculator calculator = new PriceCalculator();
System.out.println("坐16千米公交车票价:" + calculator.busPrice(16));
}
private int busPrice(int km) {
int extraTotal = km - 10;
// 超出10km部分 每5km需额外付1元 不足5km按照5km计算
int extraFactor = extraTotal / 5;
int fraction = extraTotal % 5;
int price = 1 + extraFactor * 1;
return fraction > 0 ? ++price : price;
}
}
复制代码
这很简单嘛,咱们不假思索就能写出来了。 次日,小A又要外出了,这时公交车没有来,来了辆出租车,小A选择了坐出租车。 也很简单,只须要在PriceCalculator中添加一个出租车的方法就能够了ui
public class PriceCalculator {
public static void main(String[] args) {
PriceCalculator calculator = new PriceCalculator();
System.out.println("坐16千米公交车票价:" + calculator.busPrice(16));
System.out.println("坐16千米出租车票价:" + calculator.taxiPrice(16));
}
private int busPrice(int km) {
int extraTotal = km - 10;
// 超出10km部分 每5km需额外付1元 不足5km按照5km计算
int extraFactor = extraTotal / 5;
int fraction = extraTotal % 5;
int price = 1 + extraFactor * 1;
return fraction > 0 ? ++price : price;
}
private int taxiPrice(int km) {
//10km内按起步价10元收费,超出部分每千米收费2元
if (km < 10) {
return 12;
} else {
return 16 + (km - 10) * 2;
}
}
}
复制代码
第三天,小A想换乘地铁了,一样的,往PriceCalculator中添加一个乘坐地铁的方法subPrice()便可,spa
System.out.println("坐地铁票价:" + calculator.subPrice(16));
private int subPrice(int km) {
int extraTotal = km - 6;
int extraFactor = extraTotal / 5;
if (km < 6) {
return 3;
} else {
return 3 + extraFactor;
}
}
复制代码
等等,这样太麻烦了,每次调用一次出行方案,都得调用不一样的方法,那若是方法有5个10个,那不就太混乱了?没错,咱们能够用一个方法来统一管理出行方案,经过一个字段来判断选择哪一种出行方式啊。说干就干
public int calculatorPrice(int km, int type) {
if (type == BUS) {
return busPrice(km);
} else if (type == TAIX) {
return taxiPrice(km);
} else if (type == SUBWAY) {
return subPrice(km);
}
return -1;
}
复制代码
System.out.println("坐16千米公交车票价:" + calculator.calculatorPrice(16, PriceCalculator.BUS));
System.out.println("坐16千米出租车票价:" + calculator.calculatorPrice(16, PriceCalculator.TAIX));
System.out.println("坐地铁票价:" + calculator.calculatorPrice(16, PriceCalculator.SUBWAY));
复制代码
如今调用起来比以前方便多了,但也使得calculatorPrice()逻辑变更比较混乱了,这时候还只有3种出行方案,若是须要添加一个新的出行方案,好比坐飞机、好比乘船、好比自驾等等,每多出一个方案就会让这里面的if else 变长,这会使得这个类愈来愈难以维护。更甚者,若是要取消一种出行方案,涉及到减小if else的时候,这时候就会很头疼,由于这种类通常都会做为公共类被调用,删除了颇有可能对其余地方形成影响。
那有什么方案优化一下吗?对于这种状况,因为咱们已经知道本身须要选择的出行方案,而又但愿能灵活切换所选方案的时候,就能够考虑策略模式了。
咱们先定义一个抽象接口,用来计算价格
public interface CalculateStrategy {
/**
* 根据距离计算价格
*
* @param km 千米 路程
* @return 价格
*/
int calculatePrice(int km);
}
复制代码
分别实现每种出行策略
public class BusStrategy implements CalculateStrategy {
@Override public int calculatePrice(int km) {
int extraTotal = km - 10;
// 超出10km部分 每5km需额外付1元 不足5km按照5km计算
int extraFactor = extraTotal / 5;
int fraction = extraTotal % 5;
int price = 1 + extraFactor * 1;
return fraction > 0 ? ++price : price;
}
}
复制代码
public class TaxiStrategy implements CalculateStrategy{
@Override public int calculatePrice(int km) {
if (km < 10) {
return 12;
} else {
return 16 + (km - 10) * 2;
}
}
}
复制代码
public class SubwayStrategy implements CalculateStrategy {
@Override public int calculatePrice(int km) {
int extraTotal = km - 6;
int extraFactor = extraTotal / 5;
if (km < 6) {
return 3;
} else {
return 3 + extraFactor;
}
}
}
复制代码
建立一个扮演Context角色的环境类
public class TrafficCalculator {
CalculateStrategy mStrategy;
public void setStrategy(CalculateStrategy strategy) {
mStrategy = strategy;
}
public int calculatePrice(int km) {
return mStrategy.calculatePrice(km);
}
}
复制代码
实现测试类
public class Test {
public static void main(String[] args) {
TrafficCalculator calculator = new TrafficCalculator();
calculator.setStrategy(new TaxiStrategy());
calculator.calculatePrice(20);
}
}
复制代码
这样咱们在选择不一样的出行方式时候,只须要经过calculator.setStrategy()方法指定对应的方式便可,其余地方的代码基本不须要变更,若是须要增长新的出行方案,也只须要新建一个具体策略类,而且实现CalculateStrategy接口便可。
策略模式简化了逻辑、结构、下降了耦合性,加强了系统的可读性、稳定性与拓展性。合理的利用策略模式,能够有效的减小一部分if else带来的复杂性问题。
在一些简单状况下,用if else能办到的事情就不必过分设计了,不要滥用设计模式,这点好像也只能从经验中不断摸索了。