23种设计模式之策略设计模式

策略模式:分别封装行为接口,实现算法组,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算

策略模式:分别封装行为接口,实现算法组,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。

策略模式注意点:1)分析项目中变化部分与不变部分;2)多用组合少用继承;用行为类组合,而不是行为的继承更有弹性。

鸭子游戏项目设计思路

一般设计是分析鸭子类别,把相同的放在抽象超类中实现,不同的在抽象超类中定义为抽象方法,然后不同的鸭子继承抽象超类,实现抽象方法

public abstract class Duck {

    public Duck() {

    }

    //鸭子都是一样的叫声
    public void quack() {
        System.out.println("~~gaga~~");
    }

    //鸭子都会游泳
    public void swim() {
        System.out.println("~~im swim~~");
    }

    //鸭子长相不一样
    public abstract void display();

}
abstract duck
public class RedHeadDuck extends Duck {
    public void display() {
        System.out.println("**RedHead**");
    }
}
RedHeadDuck extends duck
public class GreenHeadDuck extends Duck {
    public void display() {
        System.out.println("**GreenHead**");
    }
}
GreenHeadDuck

现在需求要改,鸭子会飞,那就给抽象超类添加一个fly方法,并实现会飞功能

public abstract class Duck {

    public Duck() {

    }

    //鸭子都是一样的叫声
    public void quack() {
        System.out.println("~~gaga~~");
    }

    //鸭子都会游泳
    public void swim() {
        System.out.println("~~im swim~~");
    }

    //鸭子长相不一样
    public abstract void display();

    //鸭子都会飞
    public void fly() {
        System.out.println("~~fly~~");
    }

}
超类添加鸭子会飞方法

然后又改需求,说GreenHeadDuck不能飞了,那就要在GreenHeadDuck中覆盖父类fly方法

@Override
    public void fly() {
        System.out.println("**im cant fly**");
    }
greenduck重写父类fly方法

现在问题来了,就是在父类中实现了一个方法,如果有多个子类跟父类方法不一致,那就要每个不一致的子类都要重写父类方法;如果把超类中fly定义成抽象的,那么相同fly的代码不能重用了,使用和维护上麻烦了

又有个需求,stone duck既不会飞也不会叫,那么子类中要把fly和quack重写;所以父类挖坑要子类来填,这种设计并不是好的设计

项目设计方法:分析项目变化部分和不变部分,提取变化部分,抽象成接口+实现

以鸭子游戏项目为例,假如分析得出鸭子quack和fly是变化的

根据策略模式,把变化的行为抽象成接口,flybehavior和quackbehavior

超类中定义接口对象,接口对象调用相应方法,子类只对接口对象做对应的实例化即可

public interface FlyBehavior {

    void fly();

}
行为接口FlyBehavior
public interface QuackBehavior {

    void quack();

}
行为接口QuackBehavior
public class GoodFlyBehavior implements FlyBehavior {
    public void fly() {
        System.out.println("~~good fly~~");
    }
}
FlyBehavior实现
public class GaGaQuackBehavior implements QuackBehavior {
    public void quack() {
        System.out.println("~~ga ga ~~");
    }
}
QuackBehavior实现
public abstract class Duck {

    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {

    }

    public void fly() {
        flyBehavior.fly();
    }

    public void quack() {
        quackBehavior.quack();
    }

    public abstract void display();

    public void swim() {
        System.out.println("~~swimming~~");
    }

}
抽象超类,定义了接口对象
public class GreenHeadDuck extends Duck {

    public GreenHeadDuck(){
        this.flyBehavior=new GoodFlyBehavior();
        this.quackBehavior=new GaGaQuackBehavior();
    }

    public void display() {
        System.out.println("**GreenHead**");
    }
}
子类根据自己的行为设定行为对象

同样RedHeadDuck也可以像GreenHeadDuck一样,在自己的类中设定行为对象

这样有点问题就是一旦子类定义好,就不能动态改变行为了,那么就在超类中定义接口对象的set方法,可以使新实例化后的子类设定新的行为对象