策略模式
定义:定义了一系列算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式属于行为型模式,将算法封装起来,利用多态使代码更灵活。
通常策略模式包含三个角色:
- Context 环境类,提供策略环境,负责策略之间的交互和数据传递。
- Strategy 抽象策略类,定义公共接口,各种不同的算法以不同的方式实现这接口,让Context类调用不同算法。
- ConcreteStrategy 具体策略类,具体算法实现。
策略模式在生活中到处可见,比如去旅游,你可以选择不同的交通工具,飞机、火车、汽车等都是你可以选择的策略。还有超市折扣,打8折或者满200减50。根据超市折扣的例子,我们代码会这么写。
switch (type) {
case 0:
price = price * 0.8;
break;
case 1:
if (price >= 200) {
price -= 50;
}
break;
}
type对应不同的策略,如果新增策略,随机减0-20元。就要这样写。
case 2:
int r = new Random().nextInt(20);
price -= r;
break;
每次新增策略就要修改switch语句,不小心改错了那就很麻烦了。使用策略模式将其重构。
折扣抽象策略类
public interface DiscountStrategy {
double calcPrice(double price);
}
超市环境类
public class Supermarket {
DiscountStrategy strategy;
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double calcPrice(double price){
return strategy.calcPrice(price);
}
}
各种具体策略类
public class EightStrategy implements DiscountStrategy {
public double calcPrice(double price) {
return price * 0.8;//八折优惠
}
}
public class GiveStrategy implements DiscountStrategy {
public double calcPrice(double price) {
return price >= 200 ? price - 50 : price;//满200减50
}
}
public class RandomStrategy implements DiscountStrategy {
public double calcPrice(double price) {
return price -= new Random().nextInt(20);//随机减0-20元
}
}
客户端
double price = 200;
Supermarket supermarket = new Supermarket();
supermarket.setStrategy(new EightStrategy());
supermarket.calcPrice(price);//使用八折策略 结果为160
supermarket.setStrategy(new GiveStrategy());
supermarket.calcPrice(price);//使用满200减50策略 结果为150
supermarket.setStrategy(new RandomStrategy());
supermarket.calcPrice(price);//使用随机策略
如果新增策略,只要实现另一个Strategy接口就好,不需要修改Context。哪个策略出问题就直接找哪个,更方便维护。(上面的例子命名不是很好)
总的来说,策略模式是将算法封装起来,利用多态特性使其松耦合,方便扩展。缺点是策略的膨胀,类的膨胀,而且调用者还需要知道有哪些策略。不足之处望指教。