Strategy Pattern
public abstract class Duck{
public Duck(){};
public void swim(){
System.out.println("Duck swim");
}
public abstract void display();
public void fly(){
//????????
}
}
为啥声明为抽象类?
首先因为每一个Duck子类都不会张的一样,所以display肯定是抽象方法,这样导致Duck必须为抽象类,还有OO思想中Duck本身是抽象出来的,不可能有具体的实现对象,所以必须为抽象类.
swim方法为啥是具体实现的?
因为既然是抽象出来的类,肯定子类中有很多相同的地方一样才抽象呢,这里假设swim在所有的子类中是相同的.
这里主要理解fly方法!
1. fly方法在子类中会是千变万化的,如果像下面一样直接加入,就会出问题.
public void fly(){
System.out.println("i am fly");
}
比如我有一个木头鸭子继承了Duck,我如果调用fly就会显示我会飞,这样就会出问题.
2. 然后会想到我继承Duck类,然后重写fly方法实现自己的fly方法,这样就能解决问题了,但是引入了其他问题,比如:代码将在多个子类中重写,并且继承了Duck类以后还要查看是否有需要重写的方法,运行的时候行为不容易改变,最重要的是 如果像fly这样的函数很多既不会飞也不会叫,这样要重写很多函数……等造成代码不容易维护,不是好办法.
3. 想到接口,像下面这样
public interface FlyInterface{
void fly();
}
把fly代码拿出来抽象成接口,然后在每一个Duck子类中实现自己的fly行为,这样也能实现,但是这样的话 代码量将是巨大的,每一个子类都需要这样实现,而且没有任何代码复用.
4. 把不变的东西放在一起,把变化不确定的东西提取出来
不变的东西就定义成固定的,变化的东西我们要有能动态设置他们的能力,我们把fly行为委托delegate给其他地方实现,不在Duck内部实现,在内部仅仅只是调用.
public abstract class Duck{
private FlyInterface flyInterface;
public void setFlyInterface(FlyInterface flyInterface) {
this.flyInterface = flyInterface;
}
public Duck(){};
public void swim(){
System.out.println("Duck swim");
}
public abstract void display();
public void performFly(){
flyInterface.fly();
}
}
这样我们可以动态的设置fly动作,比如我有一个ModulDuck能有Rocket的飞行速度,我们就可以很随意的添加上去,不影响其他子类,有了继承的复用好处,没有继承的包袱.
public class FlyNoWay implements FlyInterface{
public void fly() {
// TODO Auto-generated method stub
System.out.println("fly no way");
}
}
public class FlyRocked implements FlyInterface{
public void fly() {
// TODO Auto-generated method stub
System.out.println("i am fly with rocket");
}
}
public class ModulDuck extends Duck{
public ModulDuck(){
flyInterface = new FlyNoWay();
}
public void display() {
// TODO Auto-generated method stub
System.out.println("ModulDuck display");
}
}
public class Test{
public static void main(String[] args) {
Duck modleDuck = new ModulDuck();
modleDuck.performFly();
modleDuck.setFlyInterface(new FlyRocked());
modleDuck.performFly();
}
}
从结果可以看出,我想让ModulDuck对象怎么飞,就可以怎么飞了.