文章目录
- 1、策略模式
- 2、案例:促销策略
- 3、总结
- 4、在源码中的实际应用
1、策略模式
从A地到B地,出行方式可选汽车、火车、飞机中的一种
日常开发,开发工具可IDEA,可Eclipse
不管你选飞机还是火车,你最终都可以实现从A地到B地;不管你用IDEA还是Eclipse,你最终都可以开发完你的需求。 ⇒ 策略模式即:定义一系列算法并分别封装(飞机是一种实现算法、火车也是一种实现算法),这些算法可以相互替换,且算法的替换,不影响使用者达到目的。即把算法策略的使用 和 算法策略的实现分割开来。主要角色:
- 抽象策略类:接口或抽象类,定义所有具体策略类所需要实现的接口
- 具体策略类:提供策略的具体实现
- 环境类:聚合策略类,最终给客户端调用
2、案例:促销策略
一商铺做促销活动,不同节日有不同的策略,然后由促销员将活动展示给客户。
先定义抽象策略类,即所有促销策略要实现的共同接口:
public interface Strategy {
void show();
}
定义具体策略类,即不同节日的不同促销规则:
//为春节准备的促销活动A
public class StrategyA implements Strategy {
public void show() {
System.out.println("买一送一");
}
}
//为中秋准备的促销活动B
public class StrategyB implements Strategy {
public void show() {
System.out.println("满200元减50元");
}
}
//为圣诞准备的促销活动C
public class StrategyC implements Strategy {
public void show() {
System.out.println("满1000元加一元换购任意200元以下商品");
}
}
定义环境类,聚合抽象策略类,连接上下文。 比如这里的促销员把活动策略展示给客户
@Setter
public class SalesMan {
//持有抽象策略角色的引用
private Strategy strategy;
public SalesMan(Strategy strategy) {
this.strategy = strategy; //构造方法,给策略赋值
}
//向客户展示促销活动
public void salesManShow(){
strategy.show();
}
}
写个测试类,模拟客户:
public class Client {
//春节来了,使用促销策略A
SaleMan saleMan = new SalesMan(new StrategyA());
//展示促销活动给客户端
saleMan.salesManShow();
System.out.print("===========");
//中秋节到了,使用促销策略B
saleMan.setStrategy(new StrategyB());
//展示促销活动给客户端
saleMan.salesManShow();
}
运行:
如此,后续更换促销策略,或者有了新的策略,都很高扩展。
3、总结
优点:
- 策略之间可自由切换(策略类都实现了同一个接口)
- 好扩展,有新的实现策略时,新加个子实现类就可
- 避免了多重条件选择 if else
缺点:
- 客户端必须了解所有的策略类,并自行选择(上面案例中的,什么节日用什么策略,是客户端自己set的)
- 会产生很多的策略类
适用场景:
- 一个系统需要动态地选择几种算法中的一种,可将每个实现算法封装到策略类中
- 一个类定义了多种行为,且以多个 If 语句的形式对应使用,可将每个if分支改成一个策略类,代替多重if
- 各种算法彼此独立,且要求对客户隐藏具体算法实现细节
4、在源码中的实际应用
示例Demo:
public class demo {
public static void main(String[] args) {
Integer[] data = {12, 2, 3, 2, 4, 5, 1};
// 实现降序排序
Arrays.sort(data, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
}
}
以上,Arrays类的sort方法,第二个形参传入了一个Comparator接口的子实现类对象。具体的比较规则在这个子实现类去完成(Demo里用的匿名内部类)。Comparator接口就是抽象策略类,我写的匿名内部类就是具体策略类。Arrays类则是环境类,其聚合了Comparator对象,并调用其sort方法。相关源码: