一 定义
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。
策略模式让算法独立于使用它的客户而独立变化。
二 模式结构
角色介绍:
- Context:上下文环境,起承上启下的作用,屏蔽高层模块对策略、算法的直接访,封装可能存在的变化。
- Strategy:抽象的策略,通常为接口,定义每个策略或者算法必须具有的属性和方法。
- ConcreteStrategyA,ConcreteStrategyB:具体的策略,实现抽象策略中的操作。
三 实例
我们以显示生活中,到商场买东西为例,商场一般会根据不同的客户定制不同的报价策略,比如新用户不打折,消费1000元以上打九折,老用户打9折,消费900元以上打八折,VIP用户打八折,消费800元以上打七折。当然,如果不采用策略模式,可以全部用if-else对不同的客户进行判断,这样的话会造成程序臃肿,可读性和扩展性都会变差,所以我们采用策略模式。代码如下:
- 抽象的策略接口
定义每个策略必须实现的方法,这里是根据客户的消费金额计算打折后的金额。
public interface IDiscountStrategy {
/**
* 根据消费金额,计算实际花费金额
* @param count
* @return
*/
double getPrice(double count);
}
- 具体的策略
分别实现新客户、老客户、VIP客户的策略,实现抽象策略里定义的方法。
public class NewCustomerStrategy implements IDiscountStrategy {
@Override
public double getPrice(double count) {
System.out.println("-----新用户报价策略----");
if (count < 1000) {
return count;
} else {
return count * 0.9;
}
}
}
public class OldCustomerStrategy implements IDiscountStrategy{
@Override
public double getPrice(double count) {
System.out.println("-----老用户报价策略----");
if (count < 900) {
return count*0.9;
} else {
return count * 0.8;
}
}
}
public class VipCustomerStrategy implements IDiscountStrategy{
@Override
public double getPrice(double count) {
System.out.println("-----VIP用户报价策略----");
if (count < 800) {
return count*0.8;
} else {
return count * 0.7;
}
}
}
- Context角色
public class StrategyContext {
// 持有一个策略实现的引用
private IDiscountStrategy mIDiscountStrategy;
public StrategyContext(IDiscountStrategy strategy) {
this.mIDiscountStrategy = strategy;
}
public double offerPrice(double count){
return mIDiscountStrategy.getPrice(count);
}
}
- 测试代码
// 新客户
IDiscountStrategy newDiscountStrategy=new NewCustomerStrategy();
StrategyContext newStrategyContext=new StrategyContext(newDiscountStrategy);
System.out.println("您消费的金额是:"+ newStrategyContext.offerPrice(1000));
// 老客户
IDiscountStrategy oldDiscountStrategy=new OldCustomerStrategy();
StrategyContext oldStrategyContext =new StrategyContext(oldDiscountStrategy);
System.out.println("您消费的金额是:"+ oldStrategyContext.offerPrice(900));
// vip客户
IDiscountStrategy vipDiscountStrategy=new VipCustomerStrategy();
StrategyContext vipStrategyContext =new StrategyContext(vipDiscountStrategy);
System.out.println("您消费的金额是:"+ vipStrategyContext.offerPrice(800));
通过上例,我们可以看到,通过建立抽象的策略,然后将不同的策略构建成一个具体的策略实现,通过不同的策略实现算法替换,程序的可读性,扩展性都比较好。
四 优缺点
优点:
- 算法可以自由切换
- 结构清晰,使用简单直观,避免使用多重条件判断
- 耦合度相对较低,扩展方便
- 操作封装更彻底,数据更安全
缺点:
- 随着策略的增加,子类也会变得繁多。
使用场景:
- 多个子类只有在算法或者行为上 不同的场景
- 算法需要自由切换的场景