定义
定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。
可以大范围的处理掉 if—else。通俗的讲,就是将对应不同情况的策略封装起来,应用多态的机制针对不同的情况调用这些策略类。比如生活中淘宝的促销活动,满减,立减,返现都是不同的促销策略,这样就可以把这些不同的促销策略封装起来。
策略模式使用的是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。
类型
行为型
适用场景
- 系统有很多类,而他们的区别仅仅在于它们的行为不同
- 一个系统需要动态地在几种算法中选择一种
优点
- 符合开闭原则
- 避免使用多重条件转移语句
- 提高算法的保密性和安全性
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类
- 会产生很多策略类
UML类图
- 环境角色(Context):持有抽象策略Strategy的引用,可以动态修改持有的具体策略ConcreteStragety,给客户调用;
- 抽象策略角色(Stragety):这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口;
- 具体策略角色(ConcreteStrategy):实现具体算法;
代码演示
电商活动场景,满减,立减,返现都是不同的促销策略。
UML
- 策略接口
public interface PromotionStrategy {
void doPromotion();
}
- 具体的策略
public class ManJianPromotion implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("满200 减100");
}
}
public class LiJianPromotion implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("立减50");
}
}
public class FanXianPromotion implements PromotionStrategy {
@Override
public void doPromotion() {
System.out.println("返现20%");
}
}
- 策略环境
public class PromotionActivity {
private PromotionStrategy strategy;
public PromotionActivity(PromotionStrategy strategy) {
this.strategy = strategy;
}
public void executePromotion(){
strategy.doPromotion();
}
}
- 策略工厂(与享元模式简单工厂结合)
public class PromitionStrategyFactory {
private static HashMap<String,PromotionStrategy> PROMOTION_STRATEGY = new HashMap<>();
static {
PROMOTION_STRATEGY.put("manjian",new ManJianPromotion());
PROMOTION_STRATEGY.put("lijian",new LiJianPromotion());
PROMOTION_STRATEGY.put("fanxian",new FanXianPromotion());
}
public static PromotionStrategy getPromotionStrategy(String strategyName){
PromotionStrategy strategy = PROMOTION_STRATEGY.get(strategyName);
return strategy;
}
}
- 应用层
public class Test {
public static void main(String[] args) {
PromotionActivity activity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy("lijian"));
activity.executePromition();
}
}
源码中的策略模式
在JDK中有一个接口名为Comparable
public interface Comparable<T> {
public int compareTo(T o);
}
我们可以把它看作是一个策略接口,而他的子类则是具体的策略
那么所有有调用到Comparable的地方都是Context