什么是策略模式?
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
简单示例
上面说法可能过于官方接下来我们话不多说直接用代码完成一个简单示例,首先定义一个策略接口,它有一个fly的方法;
public interface StrategyInterface {
public void fly();
}
再对接口进行不同的实现,下面是策略接口的三种实现
public class NoFly implements StrategyInterface{
@Override
public void fly() {
System.out.println("不会飞");
}
}
public class BadFly implements StrategyInterface{
@Override
public void fly() {
System.out.println("飞行技术不好");
}
}
public class GoodFly implements StrategyInterface{
@Override
public void fly() {
System.out.println("飞行技术很好");
}
}
接着创建一个类,类中有个属性为策略接口
public class Duck {
//该属性为策略接口
public StrategyInterface strategyInterface;
//无参构造
public Duck() {
}
//fly方法,如果属性不为空,则调用接口中的fly方法
public void fly(){
if(strategyInterface != null){
strategyInterface.fly();
}
}
public void setStrategyInterface(StrategyInterface strategyInterface) {
this.strategyInterface = strategyInterface;
}
}
用两个类继承上面的Duck类
public class WildDuck extends Duck{
public WildDuck() {
strategyInterface = new GoodFly();
}
public void describe(){
System.out.println("这是野鸭");
}
}
public class ToyDuck extends Duck{
public ToyDuck() {
strategyInterface = new NoFly();
}
public void describe(){
System.out.println("这是玩具鸭");
}
}
最后测试一下,直接将WildDuck和ToyDuck两个类new出来再调用各自的fly();
可以看见wildDuck.fly();打印的为“飞行技术很好”,而toyDuck.fly();打印的为“不会飞”;因为我们在WildDuck和ToyDuck的构造器中分别给它们的属性strategyInterface设置了不同的接口实现,所以当调用各自fly方法的时候其实就是调用各自的接口实现。
从Arrays类中看一个策略模式的实现
先看一段测试代码
@Test
public void test2(){
// 定义一个数组
Integer[] arr = {3,6,4,1,7,9,8};
/** new一个Comparator接口并重写其中的compare方法,
其中Comparator接口可以看成是策略接口,
而new Comparator<Integer>() 就是策略接口的实现,
compare(Integer o1, Integer o2)就是具体的处理
*/
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if(o1 > o2){
return 1;
}else {
return -1;
}
}
};
// 用java.util.Arrays调用其中的sort方法,将数组和接口传入
Arrays.sort(arr,comparator);
System.out.println(Arrays.toString(arr));//输出结果为:[1, 3, 4, 6, 7, 8, 9]
}
上面的测试中用到了util包下的Arrays类,调用其中的sort方法,下面看一下sort方法的具体实现
// 该方法传入一个数组和一个Comparator接口
public static <T> void sort(T[] a, Comparator<? super T> c) {
// 判断传入接口是否为null,若是则调用类中默认的排序方法
if (c == null) {
sort(a);
} else {
// 此处就是判断是否使用经典的归并排序
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
// 若为否则传入的接口规则进行排序
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
所以我们需要自定义排序的时候,就可以实现Comparator接口,然后在里面写自己排序规则的具体处理就可以了。
总结:
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
声明:文中可能涉及到参考别人文章的,在此感谢原作者分享,支持原创,如有侵权,请联系删除,谢谢。