在讲策略模式之前我们先讲一个小案例
小明的上司叫小明写一个关于鸭子的项目,对于鸭子,可能有绿头鸭,白头鸭,然后鸭子会飞,会叫,让小明去写,小明心想,这不很简单吗,写一个鸭子超类,然后对于不同的鸭子去继承超类,然后就很快写出了代码。
超类Duck类:
public abstract class Duck {
String name;
public void setName(String name) {
this.name = name;
}
//飞
public abstract void fly();
//叫
public abstract void voice();
public void swim(){
System.out.println(name+"正在游泳!!");
}
}
写一个绿头鸭(GreenHeadDuck)继承Duck,GreenHeadDuck类:
public class GreenHeadDuck extends Duck {
public void fly() {
super.name="GreekHeadDuck";
System.out.println(name+"正在快速飞行");
}
public void voice() {
super.name="GreekHeadDuck";
System.out.println(name+"在嘎嘎叫!!");
}
}
写一个白头鸭(WhiteHeadDuck)继承Duck,WhiteHeadDuck类:
public class WhiteHeadDuck extends Duck {
public void fly() {
super.name="WhiteHeadDuck";
System.out.println(name+"正在快速飞行");
}
public void voice() {
super.name="WhiteHeadDuck";
System.out.println(name+"在嘎嘎叫!!");
}
}
最后执行Test类:
public class Test {
public static void main(String[] args) {
Duck duck=new GreenHeadDuck();
Duck duck1=new WhiteHeadDuck();
duck.fly();
duck.voice();
duck.swim();
duck1.fly();
duck1.voice();
duck1.swim();
}
}
显然,小明这么写没毛病,不过过了几天,上司又发话了,让小明给鸭子添加一个会说话鸭子,小明心想,直接在超类里写个talk方法,然后让后面的子类直接继承,如果不能说话的鸭子就重写个方法覆盖。这样想也没毛病,但是如果鸭子的种类有十几种,上百种的时候,你还得每一个子类去覆盖,想想都可怕,这就相当于超类挖个坑,每个子类都要来填,增加工作量,复杂度为O(2^N),不是好的设计方式。最后小明利用了策略模式来解决这个问题,在父类中,就说飞行,可能有好的飞行啊,漂亮的飞行,各种不同的飞行,对飞行行为写一个接口FlyBehavior 类:
public interface FlyBehavior {
void fly();
}
实现FlyBehavior类的GoodFlyBehavior类:
public class GoodFlyBehavior implements FlyBehavior {
public void fly() {
System.out.println("在完美的飞行");
}
}
然后在超类里面定义:
FlyBehavior flyBehavior;
public void fly(){
flyBehavior.fly();
}
在WhiteHeadDuck类里面实例白头鸭的具体飞行
public WhiteHeadDuck(){
flyBehavior=new GoodFlyBehavior();
}
最后再Test里面调用,这样就可以方便的添加功能。
总结:
策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口封装各种功能,此模式让算法的变化独立于算法的使用者。
策略模式的注意点:
1、分析项目中变化部分和不变部分
2、多用组合少用继承;用行为类组合,而不是行为的继承,更有弹性。