简介
1.策略模式(Strategy Pattern) 中.定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户
2.这算法实现了几个设计原则,第一,把变化的代码从不变的代码中分离出来,第二,针对接口编程而不是具体类(定义了策略接口)第三,多用组合.聚合,少用继承(客户通过组合的方式使用策略)
原理类图

说明:
从上图可以看,客户Context有成员变量 strategy获取其他的策略接口,至于需要使用那个策略,可以在构造器中指定
案例分析 鸭子项目
1.有各种各样的鸭子 然后鸭子有各种行为
2.显示鸭子的信息
传统方法分析

1.类图分析

2.代码实现
public abstract class Duck {
public Duck() {
}
public void quack() {
System.out.println("鸭子嘎嘎嘎嘎");
}
public void swim() {
System.out.println("鸭子会游泳");
}
public void fly() {
System.out.println("鸭子会飞");
}
public abstract void display();
}
public class WildDuck extends Duck {
@Override
public void display() {
System.out.println("这是野鸭");
}
}
public class ToyDuck extends Duck {
@Override
public void display() {
System.out.println("玩具鸭子");
}
@Override
public void quack() {
System.out.println("不能叫");
}
@Override
public void fly() {
System.out.println("不能非");
}
@Override
public void swim() {
System.out.println("不能游戏");
}
}
public class Client {
public static void main(String[] args) {
WildDuck duck = new WildDuck();
duck.display();
}
}
测试
这是野鸭
传统方法问题分析
1.其他鸭子,都继承了Duck类,所以fly类让所有的鸭子都会飞了,这是不正确的
2.上面说的1的问题,其实是继承带来的问题:对类的局部改动,尤其是超类的局部改动.会影响其他部分,会有溢出效应
3.为了改进1的问题,可以通过覆盖 fly 方法来解决 ==>> 覆盖解决
4.问题又来了,如果我们有一个玩具鸭子,ToyDuck 就需要覆盖所有的方法. 解决思路 ==>> 策略模式
策略模式实现类图分析与源码
1.类图分析 类图
策略模式:分别封装行为接口,实现算法族,超类里面放行为接口对象,在子类里面具体设定行为对象.原则就是:分离变化的部分,封装接口,基于接口编程各种功能.此模式让行为的变化独立于算法的使用者

2.实现代码
public interface FlyBehavior {
void fly();
}
public class GoodFlyBehavior implements FlyBehavior {
@Override
public void fly() {
System.out.println(" GoodFlyBehavior ");
}
}
public class BadFlyBehavior implements FlyBehavior{
@Override
public void fly() {
System.out.println(" BadFlyBehavior ");
}
}
public class NoFlyBehavior implements FlyBehavior {
@Override
public void fly() {
System.out.println(" NoFlyBehavior ");
}
}
public abstract class Duck {
FlyBehavior flyBehavior;
public Duck() {
}
public abstract void display();
public void quack() {
System.out.println("鸭子嘎嘎嘎嘎");
}
public void swim() {
System.out.println("鸭子会游泳");
}
public void fly() {
if (flyBehavior != null) {
flyBehavior.fly();
}
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
}
public class WildDuck extends Duck {
public WildDuck() {
flyBehavior = new GoodFlyBehavior();
}
@Override
public void display() {
System.out.println("这是野鸭");
}
}
public class PekingDuck extends Duck {
public PekingDuck() {
flyBehavior = new BadFlyBehavior();
}
@Override
public void display() {
System.out.println("北京鸭子");
}
}
public class ToyDuck extends Duck {
public ToyDuck() {
flyBehavior = new NoFlyBehavior();
}
@Override
public void display() {
System.out.println("玩具鸭子");
}
}
测试
public class Client {
public static void main(String[] args) {
WildDuck duck = new WildDuck();
duck.display();
duck.fly();
System.out.println("改变野鸭的飞行行为");
duck.setFlyBehavior(new NoFlyBehavior());
duck.fly();
System.out.println("-------------------------");
PekingDuck duck2 = new PekingDuck();
duck2.display();
duck2.fly();
System.out.println("-------------------------");
ToyDuck duck3 = new ToyDuck();
duck3.display();
duck3.fly();
}
}
测试结果
这是野鸭
GoodFlyBehavior
改变野鸭的飞行行为
NoFlyBehavior
-------------------------
北京鸭子
BadFlyBehavior
-------------------------
玩具鸭子
NoFlyBehavior
策略模式在 JDK-Arrays 应用的源码分析
1.JDK 的 Arrays 的Comparator 就实现了策略模式
2.源码
public class TestStrategy {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 数组
Integer[] data = { 9, 1, 2, 8, 4, 3 };
// 实现降序排序,返回-1放左边,1放右边,0保持不变
// 说明
// 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..}
// 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象
// 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式
Comparator<Integer> comparator = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
if (o1 > o2) {
return -1;
} else {
return 1;
}
};
};
// 说明
/*
* public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null)
* { sort(a); //默认方法 } else { if (LegacyMergeSort.userRequested)
* legacyMergeSort(a, c); //使用策略对象c else // 使用策略对象c TimSort.sort(a, 0, a.length,
* c, null, 0, 0); } }
*/
// 方式1
Arrays.sort(data, comparator);
System.out.println(Arrays.toString(data)); // 降序排序
// 方式2- 同时lambda 表达式实现 策略模式
Integer[] data2 = { 19, 11, 12, 18, 14, 13 };
Arrays.sort(data2, (var1, var2) -> {
if (var1.compareTo(var2) > 0) {
return -1;
} else {
return 1;
}
});
System.out.println("data2=" + Arrays.toString(data2));
}
}
JDK源码
public interface Comparator<T> {
int compare(T o1, T o2);
}
public class Arrays {
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
}
lambda表达式 代码在上面测试部分
策略模式注意事项和细节
1.策略模式的关键是:分析项目中变化部分和不变部分
2.策略模式的核心思想是:多用组合/聚合 少用继承,用行为类组合,而不是行为的继承,更加有弹性
3.体现了"对修改关闭,对拓展开放"原则,客户端增加行为不同修改原有代码,只要添加一种策略(模式)即可,避免了使用多重转移语句(if - else -else if -else)
4.提供了可以替代继承关系的办法:策略模式将算法封装到独立的 Strategy 类中使得你可以独立与Context改变他,使得它易于切换,易于理解,易于拓展
5.需要注意的是:没添加一个策略都要增加一个类,当策略过多的时候会导致类数目庞大